A module claims; it does not list its rivals. And flavor is retired.
Three decisions, all Jochen's, and the first is the one that unlocked it. Exclusivity is not a property of a module. It is a property of a singular resource the module takes over. Two shells compete for nothing and any number may be installed; two display servers both want the seat. So a module declares what it CLAIMS, and two modules claiming the same thing cannot both be assigned within that claim's scope. Not "xorg conflicts with wayland". Pairwise exclusion has a property that only shows up later: adding a third display server means editing xorg and wayland to know about it. Every new module requires changing modules nobody who wrote it owns, and the edits grow as the square of the count. With a claim the third one says what it claims and nothing else changes anywhere. Claims have a scope -- node, site, mesh -- which is not new. The mesh already enforces exactly one hub with a unique index. Scope is that idea said once rather than hard-coded per case. And some conflicts need no claim at all: two modules declaring the same file or binding the same port are visible from what they declare. A claim is only written for the abstract ones. A requirement with several answers is refused, never guessed. One candidate is assigned silently because there was no choice to make; none is refused naming what is missing; several is refused naming them. That is what makes a solver unnecessary -- counting candidates has no surprising behaviour, and a solver can be added later without changing a single manifest. Flavor is retired. It was carrying three unrelated meanings: variants of a thing, a subset of a module a node installs, and whatever the current system does, which earned two knowledge-base entries about going wrong. A word with three meanings cannot be reasoned about. What it reached for is two ordinary things -- different modules providing the same thing, and one module with a setting.
This commit is contained in:
@@ -84,7 +84,7 @@ The decomposition is impossible while a feature is a singleton per module.
|
||||
|---|---|---|
|
||||
| 1.1 | Decision record — named features, per-node opt-in (next free number) | accepted |
|
||||
| 1.2 | Manifest: declared `features:` with type + directory | a module declares two of one kind and both build |
|
||||
| 1.3 | Selection: `always` / flavor-selected / `optional` | a node installs a subset; artifacts stay flavor-blind |
|
||||
| 1.3 | Selection: `always` / `optional` | a node installs a subset; artifacts stay selection-blind |
|
||||
| 1.4 | `requires:` moves onto the feature | a schema feature's database is not provisioned where the feature is not installed |
|
||||
| 1.5 | Assignment carries the opted-in feature set | opting a node in requires no rebuild |
|
||||
|
||||
@@ -103,7 +103,7 @@ Cheapest first, and each one proves the extraction pattern before the expensive
|
||||
| 2.2 | `hal/stream` — the record; notifications and messaging as views | axon, synapse, notifications, meetings, conversations | medium |
|
||||
| 2.3 | `hal/agents` — identity, licence, runs, memory, thoughts | noxflow agents, `hal/thoughts` | **high** — touches credentials |
|
||||
| 2.4 | `hal/work` — what remains of noxflow | noxflow tasks | medium |
|
||||
| 2.5 | `hal/ai` — provider integration, flavored | `hal/claude*` | medium |
|
||||
| 2.5 | `hal/ai` — one module per provider, each providing *a model provider* | `hal/claude*` | medium |
|
||||
|
||||
Each extraction is expand-then-contract: new context alongside, dual-write, verify, cut
|
||||
over, remove. **Never a move commit.**
|
||||
|
||||
Reference in New Issue
Block a user