Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -17,6 +17,15 @@ touches:
|
|||||||
Whether the catalogue's missing structure is a **graph** — modules declaring what they need,
|
Whether the catalogue's missing structure is a **graph** — modules declaring what they need,
|
||||||
what they offer, and what they exclude — and what that replaces.
|
what they offer, and what they exclude — and what that replaces.
|
||||||
|
|
||||||
|
**[`features.md`](features.md) answers what happens to `feature`.** It is one word for four
|
||||||
|
things spanning three tiers — artifacts built once per version, resources applied to a machine,
|
||||||
|
actions run against something that is not this machine, and checks that are requirements in
|
||||||
|
disguise. Measured: every one of the twenty-one handlers implements all six stages, so `configs`
|
||||||
|
has a build stage with nothing to build and `npm` has a start stage with nothing to start. That
|
||||||
|
emptiness is the conflation, and it is why a stage that did nothing and a stage that failed look
|
||||||
|
alike. Nothing replaces it, because it was never one concept. **One property is worth keeping:
|
||||||
|
content is detected, relationships are declared.**
|
||||||
|
|
||||||
**[`cases.md`](cases.md) enumerates what a module can be** — twenty kinds of thing the mesh has
|
**[`cases.md`](cases.md) enumerates what a module can be** — twenty kinds of thing the mesh has
|
||||||
to install, run, own or know about — and extracts the axes a manifest must express. Two of those
|
to install, run, own or know about — and extracts the axes a manifest must express. Two of those
|
||||||
axes appear in no current thinking: **how many instances** a thing may have, and **whether two
|
axes appear in no current thinking: **how many instances** a thing may have, and **whether two
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# What a feature is, and what it splits into
|
||||||
|
|
||||||
|
Measured against `origin/main` of the code repository, 2026-08-26.
|
||||||
|
|
||||||
|
The operator wants the feature concept gone.
|
||||||
|
[Research 006](../006-mesh-from-scratch/00-overview.md) left it open — *"does `feature`
|
||||||
|
survive? The skeleton splits it in two and argues the conflation is what makes the delivery
|
||||||
|
pipeline hard to reason about."*
|
||||||
|
|
||||||
|
This is what it actually is, and what it turns into.
|
||||||
|
|
||||||
|
## What it is today
|
||||||
|
|
||||||
|
A **feature** is a kind of content a module can carry, detected from what its directory
|
||||||
|
contains rather than declared. Twenty-one of them, each with a handler that owns its whole
|
||||||
|
lifecycle:
|
||||||
|
|
||||||
|
```
|
||||||
|
configs dist-assets events hooks migrations migration-artifact npm npm-install
|
||||||
|
prerequisite-env prerequisite-packages prerequisite-provision provision-migrations
|
||||||
|
provision-seeds seeds service systemd tools verifiers verify vhost detect
|
||||||
|
```
|
||||||
|
|
||||||
|
Each moves through **six stages**: build, publish, install, configure, start, verify.
|
||||||
|
|
||||||
|
## Finding — every handler implements every stage
|
||||||
|
|
||||||
|
The structural evidence, and it is not a style problem.
|
||||||
|
|
||||||
|
| handler | stages it implements |
|
||||||
|
|---|---|
|
||||||
|
| `configs` | build · configure · install · start · verify |
|
||||||
|
| `service` | build · configure · install · start · verify |
|
||||||
|
| `systemd` | build · configure · install · start · verify |
|
||||||
|
| `tools` | build · configure · install · start · verify |
|
||||||
|
| `vhost` | build · configure · install · start · verify |
|
||||||
|
| `migrations` | build · configure · install · start · verify |
|
||||||
|
| `npm` | build · publish · install · configure · start |
|
||||||
|
|
||||||
|
`configs` writes files onto a node. It has nothing to build, and it has a build stage.
|
||||||
|
`npm` publishes a package to a registry. It has nothing to start, and it has a start stage.
|
||||||
|
|
||||||
|
**One interface spans build-time and apply-time, so every kind of content must implement both
|
||||||
|
halves and most of them do nothing in one.** That is the conflation, and the emptiness is what
|
||||||
|
makes the pipeline hard to reason about: a stage that does nothing and a stage that failed to
|
||||||
|
do anything look identical from outside.
|
||||||
|
|
||||||
|
## What it splits into
|
||||||
|
|
||||||
|
The twenty-one are not one kind of thing. They are four, and they belong to different tiers.
|
||||||
|
|
||||||
|
**Artifacts — built once per version, then published.** `npm`, `dist-assets`,
|
||||||
|
`migration-artifact`. Nothing about a node is involved; the output is a thing that exists in a
|
||||||
|
registry. **Tier 2, delivery.**
|
||||||
|
|
||||||
|
**Resources — desired state on a machine.** `configs`, `service`, `systemd`, `vhost`, `tools`.
|
||||||
|
Applied, converged, idempotent — which is exactly what
|
||||||
|
[ADR 0043](../../02-DECISIONS/0043-a-declaration-is-an-ordered-list-of-owned-resources.md)
|
||||||
|
already describes and what the host already does. **Tier 0.**
|
||||||
|
|
||||||
|
**Actions — run once, against something that is not this machine.** `migrations`, `seeds`,
|
||||||
|
`provision-migrations`, `provision-seeds`, `hooks`. A migration runs against a database, and the
|
||||||
|
database may be on another node entirely. Neither an artifact nor node state, which is why they
|
||||||
|
sit awkwardly in a scheme built for both. **Tier 2, and the operator wants seeds gone.**
|
||||||
|
|
||||||
|
**Checks — assertions, not changes.** `prerequisite-env`, `prerequisite-packages`,
|
||||||
|
`prerequisite-provision`, `verify`, `verifiers`, `detect`. The prerequisites are **requirements
|
||||||
|
in disguise** — a module saying what must be true before it can be installed, which is precisely
|
||||||
|
what an edge in the graph says. The verifiers are the read-back the host already performs.
|
||||||
|
|
||||||
|
## So the answer is: it splits, and the split is a tier boundary
|
||||||
|
|
||||||
|
**`feature` is one word for four things spanning three tiers.** That is why every handler
|
||||||
|
implements every stage, why half of them are empty, and why the pipeline is hard to reason
|
||||||
|
about.
|
||||||
|
|
||||||
|
Nothing replaces it, because it was never one concept:
|
||||||
|
|
||||||
|
| Was a feature | Becomes | Whose |
|
||||||
|
|---|---|---|
|
||||||
|
| npm, dist-assets, migration-artifact | an **artifact** | delivery |
|
||||||
|
| configs, service, systemd, vhost, tools | a **resource** in a declaration | the host |
|
||||||
|
| migrations, hooks | an **action** against something else | delivery |
|
||||||
|
| seeds | *nothing* — the operator wants them gone | — |
|
||||||
|
| prerequisite-* | an **edge** in the graph | the catalogue |
|
||||||
|
| verify, verifiers | the host's **read-back** | the host |
|
||||||
|
|
||||||
|
## What is lost, and should not be
|
||||||
|
|
||||||
|
**Detection.** Features are detected from the directory rather than declared, and the reason is
|
||||||
|
good: *a declared list and the directory it describes drift, and the directory is the one that
|
||||||
|
is true.* That property is worth keeping whatever the concept is called — a module that says it
|
||||||
|
has migrations and has none, or has them and does not say so, is a fault nobody sees until it
|
||||||
|
matters.
|
||||||
|
|
||||||
|
Under the split, detection still applies: what a module **contains** is read from what is there.
|
||||||
|
What it **requires**, **provides** and **excludes** is declared, because none of that is visible
|
||||||
|
in a directory.
|
||||||
|
|
||||||
|
That line is worth stating precisely, because it is the one the current design got right:
|
||||||
|
**content is detected, relationships are declared.**
|
||||||
|
|
||||||
|
## Open
|
||||||
|
|
||||||
|
- **Is an action a resource?** A migration is not node state and not an artifact. It could be a
|
||||||
|
resource type the host applies with the target being a database rather than a machine — which
|
||||||
|
would collapse the third category into the second, at the cost of the host reaching something
|
||||||
|
that is not the machine it is on. That cost looks too high, but it has not been argued.
|
||||||
|
- **Where do hooks go?** They are arbitrary code a module runs at a stage — the escape hatch. A
|
||||||
|
design with no escape hatch is either very good or has not met reality yet, and this one has
|
||||||
|
not.
|
||||||
|
- **What does the pipeline schedule, once features are gone?** It currently schedules features.
|
||||||
|
If the four categories have different lifecycles, the unit of work is different for each, and
|
||||||
|
what the coordinator orchestrates needs naming.
|
||||||
Reference in New Issue
Block a user