Synced from `specs/repo.yaml` and `specs/task-routing.yaml`
Stable root inventory
9 stable roots
contractcoreroutermiddlewaresecuritystorehealthlogmetrics
Stable roots are the long-lived public packages at the repository root. They define the default learning path, carry the narrowest public contract Plumego intends to preserve, and give the canonical app path something stable to stand on.
Synced from `specs/repo.yaml` and `specs/task-routing.yaml`
9 stable roots
contractcoreroutermiddlewaresecuritystorehealthlogmetricsSynced from `specs/repo.yaml` and `specs/task-routing.yaml`
Change kernel, lifecycle, route structure, transport contracts, transport middleware, auth primitives, or storage primitives.
aitenantnetpubsubrestvalidatorutilsfrontendThese fact blocks come from the machine-readable repository specs instead of a copied docs-only list.
A stable root is the right home when the change belongs to the default service path Plumego expects every maintainer to understand.
That usually means one of four things:
If the change needs capability policy, tenant-aware branching, topology-heavy behavior, or feature-family discovery, you are already pushing beyond the stable-root contract.
Use this quick test before you choose a stable root.
reference/standard-service still be a valid example if this code existed only in the stable root?If the answer turns into “only for some capabilities” or “only when a specific product policy is active,” the safer home is usually an owning x/* family instead.
The current repository already provides concrete module-level boundaries that make this easier to judge.
| Stable root | Keep it here when the work is about | Move out when the work becomes |
|---|---|---|
core | app construction, route attachment, middleware attachment, Prepare / Server / Shutdown lifecycle | feature catalogs, tenant policy, debug metadata, or capability-specific runtime behavior |
middleware | transport-only wrappers such as request IDs, tracing hooks, access logging, auth/security transport adapters, and HTTP metrics | tenant resolution, quota policy, API version negotiation, or protocol/payload adaptation |
store | narrow persistence contracts and base abstractions such as store/file, store/kv, store/idempotency, and store/cache primitives | topology-heavy cache engines, tenant-aware adapters, signed URLs, file metadata management, SQL/provider policy, or HTTP-facing caching behavior |
These are not abstract style preferences. They are the current repository’s actual ownership lines.
Once you know the change still belongs in the stable surface, continue with the owning module primer instead of staying at the concept layer.
| If the work mainly touches | Open this primer next | Why this primer matters |
|---|---|---|
| lifecycle, explicit app construction, logger injection, and route attachment | Core Primer | it turns the stable-root rule into the actual core lifecycle and kernel boundary |
| transport wrappers, request IDs, tracing hooks, access logging, auth/security HTTP adapters, and rate-limit adapters | Middleware Primer | it shows what still counts as transport-only and what must move to x/tenant, x/rest, or x/gateway |
| file contracts, cache primitives, KV helpers, idempotency contracts, and DB helper boundaries | Store Primer | it gives the clearest concrete split between stable persistence primitives and x/data, x/data/cache, x/fileapi, or x/tenant work |
A few recurring examples make the boundary clearer.
core, explicit app construction and one canonical lifecycle path stay stable, but debug snapshots belong in x/observability/devtools and feature-specific wiring belongs in app-local code or an extension.middleware, request IDs, tracing hooks, access logging, and HTTP metrics stay stable because they are still transport-only. API version negotiation moves to x/rest/versioning, while protocol adaptation moves to x/gateway/*.store/file, shared file contracts and errors stay stable, but tenant-aware storage backends and metadata persistence move to x/data/file, and upload/download HTTP endpoints move to x/fileapi.store/cache, base cache primitives stay stable, but distributed cache behavior moves to x/data/cache, HTTP response caching moves to x/gateway/cache, and tenant-aware cache adapters move to x/tenant/store/cache.Readers often misclassify a change as stable-root work just because it feels foundational. The current repository pushes back on that instinct.
core.middleware.store.The stronger question is whether the behavior remains narrow, default, and capability-agnostic after you implement it.
When a stable-root candidate starts learning extension semantics, use the owning destination instead of stretching the root.
x/tenantx/gatewayx/restx/observabilityx/data, x/data/cache, or x/fileapi