|
2 | 2 |
|
3 | 3 | **Date:** 2026-06-26 |
4 | 4 | **Status:** Step 0 landed in v0.0.67 (candidate selection is now identity-first); |
5 | | -§5 `PackageLocator` / `IdentityIndex` choke-point consolidation remains follow-up |
| 5 | +§5 `PackageLocator` / `IdentityIndex` choke-point consolidation remains follow-up. |
| 6 | +**Partly superseded by #278 (v0.0.105):** §4.5's emit half landed (`mcpp emit xpkg` |
| 7 | +now writes both `namespace` and the FQN `name`); its "catalog keys on canonical |
| 8 | +(ns,name)" half is **unachievable as written** — the catalog belongs to xlings, is |
| 9 | +keyed by the literal `package.name` with exact `find()`, and mcpp's normalization |
| 10 | +has no authority over it, so the split/FQN equivalence is instead resolved by |
| 11 | +constraining the wire key's spelling (INV-NAME). §4.6(c)'s discovery rung is |
| 12 | +narrowed — see the SUPERSEDED note at that row. |
6 | 13 | **Extends:** [`2026-06-20-package-resolution-architecture.md`](2026-06-20-package-resolution-architecture.md) |
7 | 14 | (realizes its deferred §5 `PackageLocator` / identity-indexed slow path), |
8 | 15 | [`2026-05-11-namespace-field-design.md`](2026-05-11-namespace-field-design.md), |
@@ -389,7 +396,30 @@ declared `(∅, a.b.c)` in the `a.b`-owned index. The user's point, encoded. |
389 | 396 | | candidate kind | rule | matches `(aimol, tensorvia-cpu)`? | |
390 | 397 | |---|---|---| |
391 | 398 | | qualified, ns non-empty | **exact tuple equality** `cand == declared` | `(aimol, tensorvia-cpu)` ✅ · `(mcpplibs.aimol, …)` ❌ · `(mcpplibs, …)` ❌ | |
392 | | -| discovery, ns = `∅` | match by `name` alone across the precedence path; **resolve to the declared `(ns, name)`** before returning | `(∅, tensorvia-cpu)` ✅ → resolves to `(aimol, tensorvia-cpu)` | |
| 399 | +| discovery, ns = `∅` | ~~match by `name` alone across the precedence path~~ **SUPERSEDED — see the note below**; **resolve to the declared `(ns, name)`** before returning | ~~`(∅, tensorvia-cpu)` ✅ → resolves to `(aimol, tensorvia-cpu)`~~ | |
| 400 | + |
| 401 | +> **SUPERSEDED by #278 (mcpp 0.0.105).** The discovery rung is **not** a |
| 402 | +> cross-namespace wildcard. It is the "upstream package that declares no |
| 403 | +> `namespace`" rung, and a hit whose descriptor declares a non-empty namespace is |
| 404 | +> now REJECTED at the dependency-resolution call site (`selectDependencyCandidate` |
| 405 | +> in `prepare.cppm`; the gate itself is unchanged, because `mcpp new --template X` |
| 406 | +> still discovers by short name). A bare `[dependencies]` key therefore resolves in |
| 407 | +> exactly three places: `mcpplibs`, `compat`, and no-namespace upstream packages. |
| 408 | +> |
| 409 | +> Why the reversal: "match by name alone across the precedence path" makes |
| 410 | +> resolution depend on which indices happen to be present. Two namespaces owning |
| 411 | +> the same short name would be settled by an index ordering that has **no total |
| 412 | +> order** across user-added `[indices]`, and adding an index could silently |
| 413 | +> retarget an existing dependency. Reproducibility beats the convenience. |
| 414 | +> |
| 415 | +> The **P3 half of this row still stands and is now actually implemented**: a |
| 416 | +> discovery hit writes back the namespace the DESCRIPTOR declares, not the |
| 417 | +> candidate's empty one. Caveat: an empty declared namespace is a legal identity |
| 418 | +> for upstream bare packages, not a hole to fill — the "no empty namespace ever |
| 419 | +> reaches the install layer" claim in §4.4 presumes §4.1 index-owned namespace |
| 420 | +> attribution, which remains unimplemented. |
| 421 | +> |
| 422 | +> See `.agents/docs/2026-07-25-issue278-descriptor-name-form-canonicalization-design.md` §3.2. |
393 | 423 |
|
394 | 424 | **Selection** = first candidate (in the §(a) order) that finds a declared identity by |
395 | 425 | rule §(c). Crucially, "finds" means **an entry with that declared identity exists in |
|
0 commit comments