Monorepo RFC 006 l4 distribution forms
RFC-006 — L4 Distribution Forms: how a Sector reaches the world
| Field | Value |
|---|---|
| Status | *ccepted*(2026 |
| Author(s) | Rodrigo (with Claude as scribe) |
| Date | 2026 |
| Affects | Classification of fourth-level directories within each Sector; renames site/ → landing/; renames lib/ → engine/ (engines/ Domain only); restructures meta/sites/ |
| Depends on | monorepo-RFC-005-l3-sector-definition.md |
1. Summary
Define *istribution form*as the L4 level of the monorepo taxonomy: the category of artifact through which a Sector is delivered to the consumer. This is the first level with a *losed, uniform vocabulary*— every distribution form has the same name across all Sectors, all Areas, and all Domains, regardless of the Sector's nature.
This RFC also resolves two consequential problems:
- The vocabulary collision between L2
meta/sites/and L4<sector>/site/,by renaming the L4 form to
landing/. - The misleading
meta/sites/opacity, by introducing an explicit subfolderstructure that names what each site represents.
2. Why a closed vocabulary at L4
Levels L1, L2, and L3 each apply a distinct criterion (consumption, theme, identity), but they let the terms vary by branch. L4 is different: every distribution form ties to a *pecific platform target, runtime, and packaging channel* all of which carry well-defined tooling, conventions, and CI pipelines.
A closed vocabulary at L4 is mandatory because:
- *ooling depends on it.*
/k-parity,/k-test,/k-manifest, the SDKlints, and the CI matrix all key off the L4 folder name. Without a fixed set, every tool would need a discovery layer.
- *5 hangs off it.*The next level (RFC-007) is *language and framework
conventions inside a distribution form* — Flutter conventions live inside
app/mobile/andapp/desktop/; Go conventions live insidebackend/andapp/cli/. Stable L4 names are a precondition for stable L5 rules. - *t eliminates synonym drift.*Without a closed set,
app/android/,mobile/,app/flutter/would all eventually appear in different Sectors meaning the same thing. The closed set forces every Sector to use the same name for the same artifact.
3. The closed vocabulary
| Folder | Artifact type | Platform target |
|---|---|---|
backend/ |
HTTPgRPCWebSocket server of the Sector | Linux server (Koder hosts) |
app/mobile/ |
Flutter app | Android + iOS |
app/desktop/ |
Flutter app | Linux + macOS + Windows |
app/tv/ |
JS/React app | TizenOS + WebOS |
app/web/ |
Web app: PWA, SaaS, admin console | Browser |
app/cli/ |
Command |
LinuxmacOSWindows |
app/tui/ |
Terminal UI (interactive, full-screen — Bubble Tea, Ratatui) | LinuxmacOSWindows |
engine/ |
Embeddable artifact (library, framework, SDK, runtime, component library, binding) — *xclusive to Sectors in the engines/ Domain* |
Multiple languages |
landing/ |
Marketing landing page for the Sector | Web (<sector>.koder.dev) |
<brand>/ |
B2B brand variant in an engine + product pair | Same runtime as the Sector, packaged under a different brand |
3.1 The semantic structure of L4
The folders cluster into four buckets along the same consumption axis used at L1:
backend/ ← consumed by API
app/{mobile,desktop,tv,web,cli,tui} ← consumed by direct human interaction
engine/ ← consumed by embedding (engines/ Domain only)
landing/ ← consumed by reading
<brand>/ ← brand-packaged variant of any of the aboveThis is not a coincidence. The criterion at L1 (form of consumption) reappears at L4 as a decomposer of the Sector: a Sector is a coherent identity that can be consumed in multiple ways, and L4 enumerates those ways.
engine/ is exclusive to the engines/ Domain
The L4 form engine/ only appears inside Sectors of the engines/ Domain. This is a deliberate constraint that gives the name discriminative power: seeing engine/ anywhere in a path immediately signals that the path is inside the engines/ Domain.
Why singular vs plural matters:
| Level | Term | Scope |
|---|---|---|
| L1 | engines/ (plural) |
Domain — the collection of Sectors consumed by embedding |
| L4 | engine/ (singular) |
The single embeddable artifact inside one Sector |
engine/ (singular) is *ever*used in products/, services/, infra/, or meta/ Sectors. RFC-002 explicitly retired the generic engine/ folder in product/service Sectors (where it had been used for the consumer-side backend, now renamed backend/). The reintroduction of engine/ as the L4 form is contextually disjoint — only inside the engines/ Domain — and therefore unambiguous.
Why engine/ and not lib/: a Sector in engines/ may be a pure library (koder_ipc), a framework (koder_kit), an SDK (sdk/go), a runtime (lang/kode), a component library (koder_web_kit), or a binding (kodec/c). The umbrella term that covers all of them — and matches the L1 Domain name — is "engine" in the technical sense (RFC-002): a reusable algorithmic component, stateless, portable, embeddable. lib/ is too narrow.
3.2 app/ as the umbrella for human-facing artifacts
All distribution forms consumed by direct human interaction live under app/, distinguished by surface (mobile, desktop, TV, web, CLI, TUI). This makes `app