Skip to content

Commit dcd9753

Browse files
committed
design: the migration corrected against the consumer, and an implementation plan
Step 1 of the migration refused deps everywhere. That counts the wrong denominator: the three manifests that declare the key are consumed, and a consumer pins an exact version, so a refusal reaching a dependency's manifest makes riscv-virt-rt@0.6.0 unbuildable for everyone who pinned it while no republished version reaches them. The refusal applies to the root manifest, where the author can act on it; a dependency's is honoured and reported once. Section 16 splits the work into eight tasks with their dependency order, and states what each review axis demands of the implementation rather than of the design.
1 parent bd1e0a7 commit dcd9753

1 file changed

Lines changed: 80 additions & 5 deletions

File tree

.agents/docs/2026-09-03-xlings-workspace-as-the-one-table.md

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,26 @@ Three manifests declare `[xlings] deps` — `aarch64-virt-rt`, `riscv-virt-rt`,
175175
mcpp's own `mcpp.toml` declares no `[xlings]` section. A deprecation window
176176
buys nothing at that size.
177177

178-
1. The merged reader ships, and `deps` becomes a hard error naming the line to
179-
write instead.
178+
**Corrected during implementation (2026-09-03): step 1 refuses in the root
179+
manifest and advises in a dependency's.** The denominator argument counts
180+
manifests that declare the key, and it is the wrong denominator: those three
181+
packages are *consumed*, and a consumer pins an exact version. A refusal that
182+
reached a dependency's manifest would make `riscv-virt-rt@0.6.0` unbuildable on
183+
the new engine for everyone who pinned it, and no republished version reaches
184+
them until each consumer re-pins. That is the shape this repository has already
185+
paid for once — a consumer must ship before the thing it depends on moves.
186+
187+
The asymmetry is not a hedge. A root manifest is the author's own file and they
188+
can fix it in the same minute they read the message; a dependency's manifest is
189+
not theirs to edit, and refusing it punishes the wrong person.
190+
191+
1. The merged reader ships. `[xlings] deps` in the **root** manifest is a hard
192+
error naming the line to write; in a **dependency's** manifest it is
193+
honoured and reported once, naming the package.
180194
2. The three packages are republished with `[xlings.workspace]` and an mcpp
181195
floor.
182-
3. An index sweep confirms the denominator. It gates nothing; if it finds
183-
manifests nobody knew about, step 1's refusal becomes an advisory for one
184-
release and a window opens after all.
196+
3. An index sweep confirms no other published manifest declares it. When the
197+
advisory has been silent across a release, the dependency path refuses too.
185198

186199
**What does not bend:** `deps` is refused with a message, never dropped in
187200
silence. `[xlings]` has no unknown-key sweep — no `kKnownXlings` list exists in
@@ -502,3 +515,65 @@ The two that mattered: reading a SubOS **state** file as though it were an
502515
authored **project** file, and asserting a blast radius without checking which
503516
environment the call runs in. Both were arguments from the shape of the code
504517
rather than from what it does.
518+
519+
## 16. Implementation plan
520+
521+
Eight tasks. T1 is the only one everything else waits on; T2, T3 and T4 are
522+
independent of each other; T7 runs after the release.
523+
524+
```
525+
T1 manifest ──┬── T2 provisioning scope ──┐
526+
├── T3 xlings module ├── T5 docs ── T6 tests ── T8 release
527+
└── T4 descriptor emitter ──┘ │
528+
T7 ecosystem ──┘
529+
```
530+
531+
| # | Task | Files | Depends on |
532+
|---|---|---|---|
533+
| T1 | The merged table: parse, both namespace positions, `""`, per-platform, `workspaceByPlatform`, `deps` root-refusal and dependency-advisory, `envs` refusal | `modules/manifest/src/{toml,types}.cppm` ||
534+
| T2 | Provisioning in project scope; the materialisation feeds both file fields | `src/build/prepare.cppm` | T1 |
535+
| T3 | `ProjectEnv` and `seed_xlings_json` lose `envs` | `src/xlings/xlings.cppm` | T1 |
536+
| T4 | `xpm.<platform>.deps` in the emitted descriptor | `src/pm/publisher.cppm` | T1 |
537+
| T5 | `docs/05` §2.13, `docs/17`, both `docs/zh/` twins | docs | T1-T4 |
538+
| T6 | Unit tests and one e2e | `tests/` | T1-T4 |
539+
| T7 | The three packages republish | `mcpplibs/{aarch64-virt-rt,riscv-virt-rt,std-freestanding}` | T8 |
540+
| T8 | Version, CI, self-review, merge, release, sandbox || T5, T6 |
541+
542+
### 16.1 What each axis demands of the implementation
543+
544+
**Architecture.** One authored key, one derived list, one provisioning pass in
545+
one scope. `XlingsConfig::deps` becomes the derived install addresses, so every
546+
existing reader — the pass, `fillXpkgDirs`, `xlingsDepBinDirs`, the file's
547+
`deps` array — keeps reading the field it reads today and none of them learns
548+
about namespaces.
549+
550+
**Stability.** The scope change moves writes off a workspace shared by every
551+
project on the machine. Nothing else about the pass changes: its result check,
552+
its stamp, its offline gates.
553+
554+
**Simplicity.** No new mechanism on either side, and the diff is smaller than
555+
the design: the parse produces two projections and everything downstream is
556+
untouched.
557+
558+
**User experience.** A key that never worked stops being documented as working;
559+
a key that did two jobs becomes one; and a version a project declares is the
560+
one that runs.
561+
562+
**Compatibility.** No manifest key is added. `[xlings] deps` keeps working in a
563+
dependency and is reported once. `[xlings.envs]` is refused, and no manifest in
564+
the ecosystem uses it — measured across the local checkouts.
565+
566+
**Cross-platform.** `workspaceByPlatform` keeps the unresolved declaration, so
567+
the descriptor a Linux host emits carries the Windows edge.
568+
569+
**Consistency.** The platform vocabulary becomes xlings' own (`macosx` shown,
570+
`macos` still accepted), and the namespace may be written in either position
571+
because both are already spellings the ecosystem uses.
572+
573+
**Upgrading without noticing.** The stamp key changes with the declared set, so
574+
one re-provision per project and then nothing. No cache is invalidated, no
575+
output path moves, and a manifest written for this loads on an older mcpp.
576+
577+
**Test coverage.** Five of the twelve criteria fail on the current engine and
578+
are the ones that prove the change; C11 exists because this repository has
579+
twice measured a fast path instead of the thing under test.

0 commit comments

Comments
 (0)