# Active conventions This document captures the **mandatory naming and structure conventions** for the Active framework codebase. Every new module, type, constant, and file must comply. Existing code that drifts from these rules is treated as audit debt and migrated module by module. The goal is single-rule homogeneity: a developer learns the convention once and applies it everywhere. No exceptions without an explicit decision recorded here. --- ## 1. Module identifier — 4-letter alias Every artifact and lib that pairs with one is identified by a stable **4-letter alias** that already lives in `svelte.config.js` as a bundler alias (`$buss`, `$conn`, `$sess`, …). The same alias is the canonical module identifier across the codebase: - **Path scoping in string values** (already enforced after audit section 2): `'buss.event.published'`, `'conn.auth_failed'`, `'sess.lifecycle.adopted'`, `'perm.client.remote_check_failed'`. - **Constant name prefix**: `BUSS_*`, `CONN_*`, `SESS_*`, `PERM_*`, `TIMR_*`, `LOGR_*`, `CACH_*`, `STOR_*`, `FMTS_*`, `FEND_*`, `ADOM_*`, `AAPP_*`, `AUTH_*`, `LANG_*`, `HTTP_*`, `SIUM_*`, `ERRS_*`. Forbidden: full English words like `BUS_*`, `CONNECTION_*`, `SESSION_*`, `PERMISSION_*`, `TIMER_*`, `LOGGER_*`, `CACHE_*`, `STORAGE_*`, `FORMATS_*`, `FRONTEND_*`. Drift on this axis is being closed in a dedicated audit pass. --- ## 2. Constant naming — `__` Every categorical module-level constant follows the pattern: ``` __ ``` - **``** — the module's 4-letter alias in caps (rule 1). - **``** — what kind of constant it is. Picked from the fixed vocabulary in section 3. - **``** — the specific value's identifier in `UPPER_SNAKE_CASE`. ### Examples ```ts // good BUSS_DIAGNOSTIC_EVENTS BUSS_DEFAULT_MAX_LISTENERS_PER_EVENT BUSS_ERR_DISPOSED SESS_EVENT_LIFECYCLE_ADOPTED PERM_METHOD_CHECK TIMR_STATE_PENDING CONN_REASON_AUTH_FAILED CACH_LIMIT_DEFAULT_MAX_ENTRIES STOR_MODULE // bad (will be flagged in audit) BUS_DIAGNOSTIC_EVENTS // wrong module prefix (rule 1) DEFAULT_TIMER_SCOPE_SEPARATOR // category before module (rule 2) PERMISSION_METHOD_CHECK // wrong module prefix (rule 1) AUTO_REAUTH_USER_IDENTITY_CHANGE // missing module prefix (rule 1) ``` ### Sub-categories When a category needs internal hierarchy, append additional segments in the `` part, not in ``: ```ts // good BUSS_LISTENER_ERROR_MODE_THROW SESS_EVENT_LIFECYCLE_ADOPTED SESS_EVENT_LIFECYCLE_REVOKED PERM_DEFAULT_REMOTE_FAILURE_BACKOFF_MS // bad BUSS_LISTENER_ERR_MODE_THROW // category split across underscores ``` --- ## 3. Category vocabulary — fixed list Only these category tokens are allowed. Adding a new category is a deliberate decision recorded in this document, not an ad-hoc choice inside a module. | Category | Use | |---|---| | `MODULE` | The module's canonical 4-letter alias as a string constant. **Single source of truth** for the module's identity. Used wherever the module's identifier is needed: logger category, error message prefix, event scope, etc. Every module declares exactly one `_MODULE = ''`. | | `ERR` | Error codes (`ErrCode` values from `$libs/errs`) | | `EVENT` | Bus or lifecycle event names (string discriminators) | | `DIAGNOSTIC_EVENTS` | Event values published through `Logger` (catalog object) | | `METHOD` | Method labels for error messages (`ensureLive(METHOD)`) | | `STATE` | Tagged-union state discriminators | | `STATUS` | Tagged-union status discriminators | | `KIND` | Tagged-union kind discriminators | | `REASON` | Tagged-union reason discriminators | | `TYPE` | Tagged-union type discriminators (when none of the above fits) | | `MODE` | Mode discriminators (e.g. listener error mode) | | `DEFAULT` | Default values for options | | `LIMIT` | Maximum / minimum values | | `ID_PREFIX` | Prefix used by ID factories | | `LOG_MSG` | Log message strings | | `ERROR_MSG` | Error message strings (technical, dev-facing). Must use a template referencing `_MODULE` for the prefix, never a hardcoded literal: `` `[${MOD_MODULE}] ...` ``. | | `ERROR_NAME` | Legacy `Error.name` strings (being replaced by `ERR` codes) | | `CONTEXT_KEY` | Svelte context keys | Categories that are **not** in this list (e.g. `AUTO_REAUTH`, `AUTO_INVALIDATE`, `BACKOFF`, `BUFFER_POLICY`, `CHANNEL_STATE`) must fold into one of the above. Examples: - `CONNECTION_AUTO_REAUTH_*` → `CONN_REASON_AUTO_REAUTH_*` if the value drives a "why this happened" branch, or `CONN_MODE_AUTO_REAUTH_*` if it configures behavior. - `CACHE_AUTO_INVALIDATE_*` → `CACH_MODE_AUTO_INVALIDATE_*`. - `CONN_BUFFER_POLICY_*` → `CONN_MODE_BUFFER_*`. When in doubt, propose the addition here before introducing it. --- ## 4. Error codes (`ErrCode`) — special case under rule 2 Error codes from `$libs/errs` follow rule 2 with category `ERR`. Each module declares one `_ERR` seed and builds the individual codes from it via `errCode(parent, segment)` so the module string never appears as a literal in error declarations: ```ts import { errCode, moduleSeed, type ErrCode, type ModuleSeed } from '$libs/errs'; export const BUSS_ERR: ModuleSeed = moduleSeed('buss'); // 'buss::' export const BUSS_ERR_DISPOSED: ErrCode = errCode(BUSS_ERR, 'disposed'); // 'buss::disposed' export const BUSS_ERR_INVALID_PAYLOAD: ErrCode = errCode(BUSS_ERR, 'invalid_payload'); export const BUSS_ERR_LISTENER: ErrCode = errCode(BUSS_ERR, 'listener'); // 'buss::listener' export const BUSS_ERR_LISTENER_FAILED: ErrCode = errCode(BUSS_ERR_LISTENER, 'failed'); // 'buss::listener.failed' ``` The constant's `` part mirrors the path segments inside the runtime value: `BUSS_ERR_LISTENER_FAILED` ↔ `'buss::listener.failed'`. The module name lives in exactly one place: `moduleSeed('buss')`. The `::` separator distinguishes module from hierarchy. `errCode` picks the right separator automatically — `::` after a seed, `.` between segments. A helper `codeToLangPath(c)` converts `'buss::listener.failed'` → `'buss.listener.failed'` for the i18n path. ### Family matching A single predicate `matches(err, family)` from `$libs/errs` covers both common cases. `family` can be: - A **module seed** (`BUSS_ERR`) — matches any error from that module regardless of hierarchy. - An **`ErrCode`** — matches the code itself or any hierarchical descendant within the same module. ```ts matches(err, BUSS_ERR_DISPOSED) // exact code matches(err, BUSS_ERR_LISTENER) // any descendant of buss::listener matches(err, BUSS_ERR) // any error declared by buss ``` --- ## 5. String values inside diagnostic / event constants Already enforced after audit section 2: ```ts // good — value carries the module scope export const CONN_DIAGNOSTIC_EVENTS = { AUTH_FAILED: 'conn.auth_failed', RECONNECT_EXHAUSTED: 'conn.reconnect_exhausted' } as const; // bad — bare value collides across modules export const CONN_DIAGNOSTIC_EVENTS = { AUTH_FAILED: 'auth_failed', // collides with auth.* events LISTENER_THREW: 'listener_threw' // collides with sess and timr } as const; ``` Rule: every string value emitted as an event identifier must start with the module's 4-letter alias (rule 1) followed by `.` and the value-specific path. --- ## 6. File and folder structure | Layer | Rule | |---|---| | `libs//` | Pure contracts: types, constants, error classes, helpers. No Svelte runes, no engine state. | | `arts//` | Runtime engine + `*.svelte.ts` active wrappers. May import from `$libs/` and from its own files. | | `arts//index.ts` | Public barrel. Re-exports the artifact's surface. | | `arts//test/` | Tests for engine and active wrappers. | | `svrs//` | Server-side counterparts (cookies, db adapters, route handlers). | | `arts/aapp/` | Composition root. Allowed to import any `$`. | **Cross-artifact imports are forbidden** (`arts/X` cannot import `$Y`). Sole exception: `arts/aapp/`. --- ## 7. When this document is updated - A new category in section 3 requires a record-of-decision: who, when, why. - Module aliases are frozen: a new artifact picks a 4-letter alias not yet taken; renaming an existing alias is a breaking change. - Drift found in the codebase that violates these rules is filed as an audit finding and resolved in a dedicated commit. Last updated: `2026-05-02` — initial version after audit-1-5.md sections 1–2 closed.