lsp-mcpp v1: compiler-agnostic C++ modules language server - #1
Open
Sunrisepeak wants to merge 93 commits into
Open
Sunrisepeak wants to merge 93 commits into
Sunrisepeak wants to merge 93 commits into
Conversation
…d LSP 3.18 protocol, S1 spec model, specs and VS Code client - mcpp package with three executables sharing src/ modules; lspmcpp.os per target selected by cfg path dependencies and consumed with if constexpr - platform: process (spawn, pipes, bounded wait), env, fs, dirs, stdio, task channels over openkal; unit tests start the test binary itself as the child - JSON from nlohmann.json, command line from mcpplibs.cmdline, tests with boost.ut (all mcpp-index modular packages); openkal-llvm-runtime 0.9.2 carries the _GNU_SOURCE fix that lets them cross-build for macOS and Windows - lsp: framing, connection to a child peer, protocol constants generated from the LSP 3.18.0 meta model by lsp-mcpp-lspgen - spec: S1 database model, P3286 module metadata, module resolution order - specs/: S1-S4 in English with JSON Schemas and validated examples - editors/vscode: thin client with language status item, 4 commands, 4 settings - design doc: D22-D25, ecosystem library reuse (12.8), openkal issue policy and log (12.9)
…e GNU target on Windows
…r crash in the release profile
…ery, normalizers, engine plans, project model - project.scan: lexical module/import scanner with UTF-16 ranges; conditional declarations are reported as uncertain - project.compdb: compile_commands.json in both forms, POSIX and Windows command splitting, response files - toolchain.probe/discover: GCC, MinGW GCC, Clang (libc++ or libstdc++), Apple clang, cl.exe, clang-cl; a persistent probe cache; compiler discovery on PATH, mcpp and xlings stores, Homebrew LLVM and Visual Studio - normalize.gnu/msvc: design 14.4 rules P1-P7 and kit arguments - normalize.plan: context selection, resolvability check that leaves out interfaces whose imports cannot resolve (E13), ambiguity, std units once - project: detection, inference from sources, mcpp and CMake providers, and a model loader that always falls back to inference
…ver core; module index boost.ut 2.3.1 does not compile with clang 22.1.8 on a Windows host (frontend crash in code generation, dev and release profiles), so the unit tests use a small named-module harness from a path dev-dependency (testing/). Recorded as K5 in the design doc's ecosystem issue log.
…onformance runner - index.modules: module-name definition (interfaces, partitions, implementation units, std from manifests), hover, import completion, outline, workspace symbols, unresolved/ambiguous/partition diagnostics, S3 graph and moduleInfo - engine.clangd: pinned clangd with modules support and dirty headers - server.session: one event loop; documents replayed into the engine after the first plan is written; requests deferred until then; watchdog, crash restart with backoff, database rewrite and restart on model or context change; cxxModules/status and the S3 requests - server.cli: serve, check (model, plan, module diagnostics and clangd --check), model (S1, compile_commands.json or the engine database), version - conformance runner and the inferred fixture: all 16 checks pass locally against clangd 23.1.0 in about 5 seconds - platform.task: copy-initialize channel values; braces wrapped JSON in an array
…xtures; libc++ from include paths; units with unresolvable imports stay out of the engine database
…mports, discovery order, timers, layout, K5 on macOS)
…ule edits reach importers VS Code writes file:///c%3A/...; clangd and the engine database use file:///C:/..., and clangd matches dirty buffers to module sources by exact path. Diagnostics come back under the client's URI. Verified with the Windows server, Windows clangd 23.1.0 and the MinGW libc++ kit under Wine: C7 passes.
…atabases; fast start from the last model - load_mcpp runs `mcpp emit build-database --format jsonl` (S2) and uses the S1 document it names; without that producer it keeps the compile database path - enrich_database completes any producer's S1 document (CMake, mcpp, a configured file): probes compilers, scans units without a role - the session saves model.json per workspace and restores the module index from it before the new model loads (design 13.1)
… end to end; release workflow; payload tooling - packaging/: payload lock (clangd 23.1.0, llvm-project 23.1.0 sources, llvm-mingw 20260826, all sha256-verified), clangd trimming, lsp-mcpp-kit assembly (libc++ configured from source for linux-x64 and darwin-arm64, extracted from llvm-mingw for win32-x64), payload assembly and verification - ci.yml: payload job per platform (Windows server cross-built on Linux), conformance fixtures per host against the payload, VS Code e2e and VSIX per platform; a composite action installs xlings, mcpp and LLVM - release.yml: reuses ci.yml, then publishes VSIX and payloads with checksums; Marketplace, Open VSX and xlings-res steps run only with credentials
…v profile; xlings packaging - server CLI accepts --stdio and --clientProcessId, which vscode-languageclient and other clients append; the VS Code end-to-end jobs failed on it - payload jobs build with the dev profile: optimized builds over openkal-windows and openkal-macos misbehave at startup (argv truncated on Windows, a segfault on macOS; recorded as K7 until root-caused) - the server uses the payload it sits in, and a kit installed by xlings - packaging/xlings: xim-pkgindex descriptor templates for lsp-mcpp and lsp-mcpp-kit; xlings_artifacts.py splits payloads into xlings-res archives and renders the descriptors; release.yml publishes them - design: K6 corrected (the runtime pins musl exactly; runtime 0.9.3 follows), K7 recorded, distribution rows updated
… and its PR; K8 recorded
…e; verification rejects such pairs The Linux kernel headers carry pairs such as xt_mark.h and xt_MARK.h. A VSIX refuses them and case-insensitive file systems fold them into one, so the kit builder keeps the all-lowercase name and the payload check fails on any pair.
…ecutable VS Code 1.110 renamed Contents/MacOS/Electron to Code and later removed the compatibility link, so test-electron 2.5 failed to spawn it on macos-14. 3.1 reads the bundle's executable and needs Node 22.
…wering After the server exits, or lets two requests in a row reach their deadline, the remaining checks fail at once with the reason instead of each waiting out its own timeout.
musl's C++ pthread_t was thirty-two bits on Windows, so every std::thread there faulted when joined (mcpplibs/openkal-musl#31, mcpplibs/openkal-llvm-runtime#18).
…tem's spelling The command interpreter scans its whole command line for switches, so an argv[0] of C:/Windows/System32/cmd.exe read /cmd.exe as /c and ran md.exe. Tests: every argument arrives unaltered, including backslashes, quotes and empty ones; on Windows the command interpreter runs in the work directory.
VS Code listens on a socket inside the user data directory, and macOS limits a socket path to 104 bytes; the default under .vscode-test in a CI checkout is longer and failed with listen EINVAL.
…he openkal releases that fix them packaging/README.md describes the payload layout, the lock, the build steps and host requirements, what verification checks, measured sizes and the release split for xlings. packaging/kits/README.md describes each platform's kit, its kit.json as built, and how the server applies a kit. The design's issue log records the detached-thread exit overflow (openkal-musl#32), the inheritable channel ends (openkal-windows#21) and the Windows argument and directory handling (openkal-windows#22).
…r stopped answering
…ws 0.7.3) A detached thread's exit no longer overruns musl's shared stack, which crashed the server on macOS when its input reader ended (openkal-musl#32). On Windows a child whose input is a channel sees its end (openkal-windows#21), and a started program receives its arguments and directory as given (openkal-windows#22).
…mporters through symbolic links mcpp names sources by their resolved path, and a macOS workspace under /var is /private/var to it. The document, the database and clangd's matching of an unsaved buffer then used different names for one file: the module was reported ambiguous and completion never saw the edit (C7 on macos-14). The workspace root, open documents and database sources now use the name with symbolic links followed; clangd receives that name, and locations in open documents return to the client under the client's own URI. CI runs mcpp-llvm through a symbolic link on Linux.
…ackslashes on Windows
The clean-machine jobs package the platform VSIX and run the main suite with the machine as the conformance fixture saw it: in a node:22-bookworm-slim container with no compiler (as root, so VS Code gets --no-sandbox), and on Windows with Visual Studio hidden and only system directories and node on PATH (usable plan W5). LSP_MCPP_E2E_ONLY selects test files for machines where only some apply.
…on run (npm starts through env bash)
A Windows workspace root's own path always contains ':' right after its drive letter; the previous encoding split the synthetic request id on the first ':', truncating the root key and misrouting the client's eventual response to no root at all. Caught by a new round-trip unit test.
…data waited for a timezone)
…s; macOS clean machine On macOS /usr/bin/clang++, c++ and xcrun are shims that open the system's "install developer tools" dialog when no developer directory exists. Discovery probed them and the SDK re-check ran xcrun every 30 s, so a Mac without the Command Line Tools would have been asked again and again. Whether tools are present is now read from the file system (DEVELOPER_DIR, the xcode-select link, the Command Line Tools and Xcode directories); without them discovery skips /usr/bin and the SDK lookup does not run xcrun. The extension's one question is the only one. Clean machine on macOS (usable plan W5, U7): Command Line Tools and Xcode hidden, fixture inferred-no-sdk (degraded, sdk-missing with the install command, a std user answered at once, module-level features), and the extension's sdk-missing suite (asked once, not again after a restart). The runner's status check matches an issue's command; check kind `responds` passes on any answer in time.
The payload integrity work (70e3bd2, W9.4) raised payload-version to 2 when it added "files"; the extension still accepted only 1 and refused every payload the packaging now assembles, so each VS Code end-to-end job failed before its first test. Versions 1 and 2 are accepted; the extension reads neither's files.
… (S2-5-1, S2-5-9); multi-root fixes
S2 5 asks a consumer to watch every entry of a database's watch list and to keep
using the last database that loaded, telling the user it may be stale, when
discovery fails. Both were the last pending S2 rules.
- base.glob: LSP glob patterns (*, **, ?, {a,b}, [...], [!...]), case following
the file system.
- A model's watch entries are registered with the client (relative patterns when
it supports them, one registration replaced by the next model's) or read by the
polling worker; files a new model brings into the watch start from what they
are rather than being reported as created. A change to one loads the model again.
- A reload whose model is unchanged (the usual answer to a saved source mcpp
watches) swaps the model and stops there: no re-reading of every source, no
replan. A replan that leaves the module graph as it was no longer closes prime
units or restarts preparation in flight.
- A project whose producer answered before and now fails keeps its model; the
status is degraded with model-stale, naming the producer's reason, until it
answers again. ProjectModel.detected tells such a failure from a project that
is no longer that kind of project.
- An mcpp that can emit a build database and fails now reports its own
diagnostic instead of falling back to build --configure-only, which wrote into
the project and replaced the reason with "did not produce compile_commands.json".
Multi-root (W9.1), failing on macOS and Windows CI since the merge:
- cxxModules/status names a root by the URI the client sent, not the canonical
path (/var vs /private/var, RUNNER~1), so per-folder status matches.
- workspace/didChangeWatchedFiles entries reach the root that owns them: a Json
brace-initialized from a Json became a one-element array, left every change
without a path, and sent all of them to the first root.
Conformance: the runner acts as an editor's file watcher for the watchers a
server registers, keeps each root's status history, and write-file can wait for a
reload (optionally of one folder) or copy content from another file; status
checks match a part of an issue's message. New fixtures mcpp-emit-watch (also run
@polling) and mcpp-emit-broken; multi-root checks a reload in its second folder.
The mock's build leaves a compile_commands.json, so an unwanted configure shows.
Traceability: 137 rules, none pending.
…erver that offers module requests - specs: S3's seven requirements carry identifiers and evidence; validate.py traces S1 to S4, 144 rules, none pending. S3 states that project.root is the folder's URI as the client sent it, and lists issue codes module-build-failed and model-stale. - server: cxxModules/status changes that keep the state are coalesced into one notification every 250 ms (S3-4-2); a new state still goes out at once. - extension: cxxModules/contexts, setContext and graph are sent only when the server declared experimental.cxxModules (S3-3-2). - conformance: a settled status that does not match yet is looked at again for up to three seconds. - ci: the Linux clean-machine container step times each phase and bounds it, and installs its packages without fsync (shared-mime-info's update-mime-database stalled the step for the whole job twice); the apt log is printed when installation fails.
… preparation progresses An interactive request (definition, hover, completion) is answered without clangd after 10 s. On a large project the modules a newly opened file imports take longer than that, so the first go-to-definition returned nothing and had to be repeated. Now, when the deadline passes while the file awaits its modules and preparation finished a module within the last 10 s, the request waits another 5 s, up to the ordinary request timeout (60 s). A request with no sign of progress is still answered at 10 s. mcpp repository (171 modules, 32 threads, dev build): the first declaration answered once at 26.2 s with no request timing out, where each earlier variant timed out once or twice before an answer at 33-35 s.
…usable plan W2.3) For a workspace without a build system, Windows prefers Visual Studio's MSVC when its toolset has the std module (D27). A toolset without one (MSVC 14.29, for instance) was skipped silently; the status now carries a notice, msvc-without-std-module, naming the toolset. A notice reduces no feature, so the state and severity stay as they are. The extension shows the first notice in the language status item's hover when there is no issue to show; until now it showed no notice at all, producer-writes-project included.
…iting files keep their cores Probing where warm starts spend their time (verbose clangd logs on the three CI hosts) showed prime units competing with the file a person opened: each `import M;` unit runs clangd's own prerequisite pass, scanning std.cppm and validating every cached BMI again, and holds one of clangd's workers (-j, physical cores) while it does. On a 2-core machine the opened file waited for a worker, then repeated the scan. - A module whose BMI clangd's persistent cache already holds, finished and at least as new as its source, completes at once without a unit, as a partition does (Primer::start_ready's `built`). The cache is read once per plan, when a module first becomes ready. - While files wait for their modules, preparation leaves each of them a core (hardware threads count as half a core except on macOS); with none waiting it uses every thread as before. timing fixture, cold and warm first navigation (median of 5 warm starts), i9-13900K pinned: 2 cores: 2.51 -> 2.35-2.49 s cold, 1.07 -> 0.80 s warm (no preparation at all: 2.15 / 0.80) 4 cores: 2.14 -> 2.12 s cold, 0.81 -> 0.81 s warm 1 core, 2 threads (clangd -j=1): 4.43 -> 4.09 s cold, 1.81 -> 1.00 s warm mcpp repository (171 modules, 32 threads): cold 25.6-26.2 -> 24.9-25.7 s (no preparation: 38.0 s), warm 5.5-5.6 -> 4.9-5.0 s.
…string that outlives its views completion-contains with "insert" split the document with base::split_lines(text_of(file)): text_of returns a temporary, so the line views dangled and the inserted text was assembled from freed memory. It failed intermittently, most often on large files: in self-lsp-mcpp the text sent to the server held a NUL and was cut short, clangd answered completion for the garbled buffer, and the check retried until its timeout (minutes in the nightly measurement). Four cold runs now pass C6 in 0.1-0.2 s.
…quests With no file waiting for its modules, preparation could open as many prime units as there are hardware threads, more than clangd's workers (-j, physical cores), so a file opened or a request made meanwhile queued behind units that take seconds each. Preparation now leaves one core for requests besides one for each waiting file. timing fixture (2 / 4 cores): 2.41 / 2.14 s cold, 0.81 / 0.81 s warm, as before. mcpp repository (32 threads): 26.3 s cold (24.9-26.2 s before, within run-to-run spread), 4.9 s warm.
…sign Usable plan section 10: the result of every work item with its evidence, where implementation departed from the plan and why, what was added beyond it (S2-5-1/S2-5-9, S3 traceability, multi-root fixes, waiting requests, module preparation policy, the runner's completion check, the mcpp#636 contract notes), measurements on the development machine, the CI hosts (nightly medians) and the two self-hosting repositories, and the upstream changes. Design section 1.3 records the measured values beside each target, section 15.1 the preparation rules the measurements led to, 12.3 and 13.1 the watch of what a producer names.
A nightly job installs the newest mcpp the index has (MCPP_VERSION=latest, which the install script now accepts) and runs mcpp-gcc and mcpp-llvm with the payload CI built, so a producer change shows up before the pinned version moves.
…1.1 (llvm/llvm-project#218152), recorded as mcpp#640
mcpp writes level 2 and leaves level 3 to the S1 library (mcpp-community/mcpp#636). lspmcpp.spec.options structures GCC/Clang and cl.exe/clang-cl arguments into SemanticOptions: what only a build needs (outputs, dependency files, optimization, debug information, warnings, BMI locations) is dropped, and what has no structured form stays under raw-semantic-arguments in order. A set's options come from its baseline-arguments, or from the arguments all its units share; a unit's delta from its local-arguments, or from what it adds to the set's. Databases a producer wrote are completed when the model loads. The options this adds are marked derived: they restate the arguments, so the engine plan keeps compiling the arguments (S1 9 rule 1 concerns the options a producer states).
…d on mcpp's answers on mcpp-community/mcpp#636: level 2 only; one set per package plus <package>:test and mcpp:std rather than per target; and visible-sets listing every other set, since the build resolves imports over one flat module graph. - mcpp-emit, mcpp-emit-package-std and mcpp-emit-watch carry that shape without ide.options; mcpp-emit gains a test that imports the package's module across sets (C10-test), and its status still asserts level 3, now reached through the S1 library. - validate.py checks the contract on every simulated database and on the S2 envelope example, which is reshaped the same way. - S1 sections 7, 9 and 11.1 gain informative text on per-package sets with flat visibility and on consumer-side completion; the level 3 example names a neutral generator. No normative change. - Design doc and usable plan record the answers, the S1 library, mcpp#640, and the short-term decision to keep the clangd/clangd 23.1.0 payload with the aligned allocation workaround.
…ocal-arguments mcpp 2026.9.15.1 writes a standard library unit's local-arguments as what follows the set's baseline, `--precompile <source> -o <bmi>`, so complete_options put the source into the unit's raw-semantic-arguments. Inputs are now removed from local-arguments the way they are from the unit's arguments. A toolchain whose stdlib names no module-metadata (mcpp describes std as units of mcpp:std) is also exported without an empty one.
A project's .xlings.json selects the mcpp that runs inside it; when that version is not
installed, xlings answers every command in its place and runs nothing. The status then said
only "mcpp did not produce compile_commands.json". It now carries what mcpp, or xlings in its
place, printed: "mcpp could not describe the project: <explanation>" (mcpp-no-database).
producer-writes-project is given only when the configure-only fallback ran and wrote into the
project, and names the mcpp version and that mcpp 2026.9.15.1 added emit build-database. The
std-module.json path (W8) stays for such older mcpp versions.
lsp-mcpp-mock-mcpp gains {"unavailable": "..."} for this case (fixture mcpp-emit-unavailable)
and declares the effects mcpp 2026.9.15.1 declares.
…database mcpp implemented mcpp-community/mcpp#636 in #639 and released it as 2026.9.15.1. CI, nightly and release now pin it, and both sides of the contract are checked against it (usable plan 10.6): - The producer: the conformance job records what `mcpp emit build-database --format json` prints for each of the host's mcpp fixtures and passes the envelopes to specs/tools/validate.py (S2 envelope and S1 schemas, S1 semantics, the #636 contract). - The consumer: mcpp-gcc, mcpp-llvm, mcpp-msvc and mcpp-llvm-msvc assert level 3, a test that imports the package's module across sets, and an unchanged workspace; multi-root's mcpp root asserts level 3. - mcpp-watch (all hosts, and @polling on Linux) runs S2 5 against mcpp itself: a new module reloads the model, a broken mcpp.toml leaves it stale with MCPP_BUILD_DATABASE_PLAN_FAILED, the repair makes it fresh. - The simulated fixtures' mcpp-mock.json files are recordings of mcpp 2026.9.15.1's output; package-std's std units now sit in a std cache directory that does not exist on CI. - Nightly: mcpp-watch joins the latest-mcpp job; self-mcpp installs the mcpp its commit's .xlings.json asks for, which xlings runs inside that repository.
Every reload a watched input caused ran `mcpp --protocol-version` before emit build-database, 0.3 s through the xlings launcher. A yes is now kept per mcpp executable and root until emit build-database fails; a no is not, so an mcpp upgraded as producer-writes-project suggests is picked up without a restart. The launcher's path does not change when the mcpp behind it does, so the executable's path, size and time (usable plan W3) cannot be the key.
A project whose module units are all .cppm and a project that separates interfaces (.cppm) from implementations (.cpp) are the two shapes lsp-mcpp has to serve; neither had a fixture on every commit, only the nightly self-hosting runs covered them. - mcpp-split: interface units and an interface partition in .cppm, two implementation units (`module hello.greet;`) in .cpp and an implementation partition. Declarations and definitions are reached from importers and tests, implementation units navigate into partitions, complete module-internal names and hover, edits reach importers, and the workspace stays unchanged. mcpp-split-gcc (Linux) and mcpp-split-msvc (Windows) are the same project with GCC 16 and msvc@system. - mcpp-all-cppm: a primary interface re-exporting two partitions and a second module, with the implementations inside the interfaces; navigation into partitions and through re-exports, completion through the re-exported module, edit propagation. Both build and run with mcpp 2026.9.15.1 on LLVM 22.1.8 and GCC 16.1.0, and passed five consecutive local rounds (15 runs, no failure). mcpp's own envelopes for them are validated by the conformance job's specifications step like the other mcpp fixtures.
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.
Implements
.agents/docs/2026-09-13-cxx-modules-unified-lsp-design.mdend to end, and then.agents/docs/2026-09-14-lsp-mcpp-v1-usable-plan.md(W1–W11) on top of it: a compiler-agnostic C++ modules language server written entirely in C++23 modules, its specifications, its conformance suite, the payload it ships with, and the VS Code extension. The execution record of the usable plan (results, deviations, measurements) is its section 10.What is in this PR
src/os/lspmcpp.ospackages selected bycfgdependencies; platform code branches withif constexprspecs/conformance/traceability.jsonconformance/lsp-mcpp-conformance: the MSVC family withimport stdwithout a developer environment (cl.exe, clang-cl, clang++ for the MSVC ABI), mcpp's ownemit build-databasewith gcc, llvm and msvc, simulated mcpp answers for what a real mcpp cannot be made to do on demand, CMake with and without build databases, multi-root, contexts, watching and reloading, payload corruption, clean machines, startup timing, self-hostingtests/,testing/lspmcpp.testingharnesspackaging/lsp-mcpp-kitassembly, payload layout, integrity and verification, xlings spliteditors/vscode/mcpp-community.lsp-mcpp): language status item, 4 commands, 4 settings, conflict prompt, Command Line Tools prompt; end-to-end tests of the packaged VSIX.github/workflows/About 100 source files (
.cppminterfaces and.cppimplementations), no header files, no preprocessor directives. JSON and command-line parsing come from mcpp-index modules (nlohmann.json,mcpplibs.cmdline).Ecosystem changes this needed
Made under the rule recorded as D25: openkal defects are fixed upstream, requirements are only recorded. Each version requirement in this ecosystem is exact, so every fix travels up through a release of each package that pins it.
_GNU_SOURCEmissing from libc++'s__config_sitefor macOS and Windows; header-wrapping modules such asnlohmann.jsondid not buildpthread_twas 32 bits on Windows; everystd::threadfaulted when joinedwcsleninto 32-bit musl)cmd.execould not read its switches, and directories carried the\\?\prefixcmd.exerefuses/, so%ComSpec%pointedcmd.exeat its own switches and CMake, Ninja and the mcpp launcher failed from a childmain; the syscall wrapper declared x1, which the kernel overwrites, an inputEach release was mirrored to GitCode and its archive hash checked against two GitHub downloads. lsp-mcpp builds on
openkal-llvm-runtime = "0.9.6"; the Windows and macOS payloads carry release servers cross-built on Linux.For mcpp itself,
emit build-databasewas proposed in mcpp-community/mcpp#636, implemented by mcpp in mcpp-community/mcpp#639 and released as 2026.9.15.1, which CI, nightly and release now pin. As mcpp's maintainers settled there, mcpp writes S1 level 2 and leaves level 3 to the S1 library (lspmcpp.spec.optionsstructures the arguments; the options it derives only restate them, so the engine still compiles the arguments);visible-setslists every other set, because mcpp resolves imports over one flat module graph; and sets are per package, plus<package>:testandmcpp:std. S1 gains informative text on both points.Both sides of that contract are checked against the released mcpp on every host (usable plan 10.6). The conformance job passes the envelopes mcpp prints for the host's mcpp fixtures to
specs/tools/validate.py(S2 and S1 schemas, S1 semantics, the #636 contract), and the fixtures then have the server consume them: level 3, a test that imports the package's module across sets, an unchanged workspace, andmcpp-watchfor reloading, a stale model on a brokenmcpp.tomland its recovery. The simulated fixtures replay recorded output of that mcpp. The loop found and fixed: standard library units'local-argumentsnaming their source, a protocol query on every reload (0.3 s through the xlings launcher), and a bare failure when a project's.xlings.jsonpins an mcpp that is not installed.The clangd 23.1.0
align_val_tregression on the MSVC STL is fixed upstream in clang 23.1.1 (llvm/llvm-project#218152) and recorded for the ecosystem as mcpp-community/mcpp#640. For now the payload stays on clangd/clangd's 23.1.0 with aligned allocation turned off in MSVC STL contexts: clangd/clangd publishes no 23.1.1, and LLVM's own 23.1.1 Linux clangd needs glibc 2.34 (#2).Recorded without a fix: MinGW
mm_malloc.h(K2),boost.utcrashes on Windows and macOS hosts (K5), libc++ wide strings over 32-bit muslwcslen(K8), two openkal requirements (K3, K4), and the deferred items listed in #2.Verification
Run 34883539883 on the head commit
8f75899passed all 18 jobs:lsp-mcpp-kit, integrity manifest, verified layoutThe nightly workflow ran once on a throwaway branch (34837141351, all jobs passed): startup timing medians over three rounds (first navigation cold/warm: Linux 5.5/2.0 s, macOS 4.4/1.9 s, Windows 8.5/2.9 s) and self-hosting on the mcpp and lsp-mcpp repositories. Its job with the latest mcpp ran the same way (34841510727, mcpp 2026.9.14.3, passed). With mcpp 2026.9.15.1 pinned, the nightly ran again on this branch (34882966882, all 25 jobs passed): lsp-mcpp self-hosted at level 3 on Linux and macOS through mcpp's own build database, the mcpp repository through the
--configure-onlyfallback of the mcpp 2026.9.14.1 its.xlings.jsonasks for, and the latest-mcpp job withmcpp-watchadded.Follow-ups that were recorded rather than done are tracked in #2.