You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .agents/docs/2026-08-29-build-rule-package-spec.md
+36Lines changed: 36 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -569,6 +569,42 @@ before, once for the directive cache and once for the advisory channel.
569
569
570
570
---
571
571
572
+
## 9a. The work, and what depends on what
573
+
574
+
The pieces below were sequenced by what each one makes verifiable, not by size.
575
+
576
+
```
577
+
I1 module name from source ─┬─► I3 collision refused
578
+
│ (I1 makes new collisions reachable;
579
+
│ they must not ship apart)
580
+
└─► I2 package-name constraint deleted
581
+
(a consequence, not a task)
582
+
583
+
B1 build-only subtree ──────► B2 rule imports its build deps
584
+
(the fix that stops (needs a resolved subtree to order)
585
+
the leak)
586
+
587
+
M0 six leaf modules ────────► M1..M3 (blocked on the M0 measurement)
588
+
589
+
engine (all of the above) ──► release ──► ecosystem rule packages
590
+
(they cannot be used by anyone
591
+
until the engine ships)
592
+
```
593
+
594
+
Nine views of the same change, each with the thing it actually decided:
595
+
596
+
| View | What it decided here |
597
+
|---|---|
598
+
|**Architecture**| The section/request split (3.3). Two orthogonal axes rather than two spellings of one, which is what makes the protobuf case expressible at all. |
599
+
|**Stability**| I1 and I3 ship together. Decoupling the module name from the package name is what makes a new collision reachable, so the refusal cannot lag behind it by a release. |
600
+
|**Simplicity**| B1 replaced a per-edge predicate with forward reachability, and the dual-role case then needed no special case. The diff removes a rule rather than adding one. |
601
+
|**User experience**| Every new refusal names both sides. The collision names two packages and two paths because with one module name shared they are the only way to tell them apart. |
602
+
|**Compatibility**| Measured, not argued: `grpcgen`, the only rule package in the index, registers the identical module name before and after, and its build is byte-identical. `[dependencies]` carrying `tools`/`host-module` is untouched. |
603
+
|**Cross-platform**| I1 exists *because* the three compiler families disagreed. The e2e cannot assert through the successful import, since GCC resolves by the declared name regardless — so it asserts on filenames, which every platform produces. |
604
+
|**Consistency**|`prepare.cppm:3924` already stated "module names are authored API"; `:4780` was the only place contradicting it. The change is a return, not an exception. |
605
+
|**Silent upgrade**| No manifest key was added (I7). A package written for the old engine builds unchanged; a package written for the new one fails to *compile* on an old engine rather than silently losing semantics, which is what the protocol version already guarantees. |
606
+
|**Test coverage**| Each assertion was observed failing against the previous behaviour before it was kept. That is what caught two wrong claims in this document. |
607
+
572
608
## 10. The framework in one view
573
609
574
610
Four layers. The only thing an author writes is L1, and what L1 emits is either
0 commit comments