================================================================================
SDOA WHITEPAPER — TECHNICAL EDITION
Version: 5.0
Date: 2026-06-17
Classification: Internal — Development Team Reference
================================================================================

This document is the single source of truth for the Self-Describing Object
Architecture as implemented in the SDOAvX project. All prior naming variants
(Service-Oriented Dispatcher Architecture, etc.) are superseded. The canonical
name is Self-Describing Object Architecture (SDOA).

--------------------------------------------------------------------------------
SECTION 1 — EXECUTIVE SUMMARY
--------------------------------------------------------------------------------

SDOA is an architectural pattern in which every module declares its own
identity, dependencies, capabilities, documentation, and version directly inside
its own definition. A lightweight registry discovers, validates, and wires
everything at startup. There are no central configuration files, no manual
registration steps, and no hidden dependencies.

SDOA is language-agnostic. The core contract — MANIFEST + DOCS + version — is
identical across Rust, Node.js, JavaScript, Python, TypeScript, and C/C++. Each
language provides its own mechanism for expressing the manifest. As of v5.0,
SDOA governs a full polyglot portfolio from UI atoms through backend workflows
through compiled Rust engines.

The architecture has evolved through five major versions (v1.0 March 2026 through
v5.0 June 2026) and currently registers 147 modules as of 2026-06-15T02:28:37Z.

--------------------------------------------------------------------------------
SECTION 2 — CANONICAL NAME CONFIRMATION
--------------------------------------------------------------------------------

Official Name:  Self-Describing Object Architecture
Abbreviation:   SDOA
Codename:       SDOAvX (the project repository)
Ratified:       C1 Resolution, 2026-06-17

> The name "Service-Oriented Dispatcher Architecture" appears in early v4.0
> specification headers and is superseded. Any file or comment using that name
> should be updated on next touch to read "Self-Describing Object Architecture."

--------------------------------------------------------------------------------
SECTION 3 — ARCHITECTURE OVERVIEW
--------------------------------------------------------------------------------

SDOA is organized around two foundational ideas:

3.1 Sovereignty Principle
--------------------------
Every module is a sovereign. A sovereign owns:
  - Its own source code
  - Its own manifest (identity, capabilities, dependencies, version)
  - Its own CSS (if a UI module)
  - Its own data files (schemas, configs, catalogs)
  - Its own variants (in a variants/ subdirectory)

No sovereign mutates another sovereign's internals. Cross-sovereign communication
happens only through declared interfaces: manifests, the EventBus, or the
StateStore API.

3.2 Three-Layer Architecture
-----------------------------
Every operation flows through exactly three layers. There are no shortcuts and
no layer-skipping allowed.

  Layer 1 — Features (Composition & Intent)
  Layer 2 — Primitives (Reusable Atoms)
  Layer 3 — Adapters / Services / Workflows / Repositories

Layer traffic rules:
  L1 -> L2 only: Features call primitives. Features never call Layer 3 directly.
  L2 -> Events only: Primitives emit events. They never call adapters or features.
  L3 <- L1 only: Only features call adapters. Primitives are unaware of the backend.
  No layer skipping: L1 never calls L3 repositories directly. L2 never calls L1.
  No circular deps: If A depends on B, B must not depend on A.

Deciding which layer a module belongs to (decision tree):
  Does it render pixels and have no business logic?  -> Layer 2 (Primitive)
  Does it compose primitives to build a screen/area? -> Layer 1 (Feature)
  Does it talk to a server, database, or service?    -> Layer 3 (Adapter/Workflow/Repository)
  If your module does two of these, split it.

--------------------------------------------------------------------------------
SECTION 4 — SDOA MANIFEST SPECIFICATION
--------------------------------------------------------------------------------

Every SDOA module carries a manifest at the top of its file. The manifest is
the module's contract with the rest of the system.

4.1 v1.2 Base Fields (Mandatory)
----------------------------------
All SDOA modules at any version must declare these fields:

  id            — Unique module identifier (e.g., "Button.prim", "Chat.workflow")
  type          — Module type (see Section 6)
  version       — Semantic version string (e.g., "1.0.0")
  runtime       — Execution environment (Browser | NodeJS | Universal | Rust |
                  Python | C++ | COBOL | VB)
  capabilities  — Array of capability strings this module provides
  dependencies  — Array of module IDs this module requires (v1.2 field name)
  docs          — Documentation object (description, author, sdoa version)
  last_modified — ISO 8601 timestamp of last change

> Non-compliant files: If a file cannot be made manifest-compliant, add the field
> "non-sdoa-compliant": true to its manifest block. All files that are touched
> must have a v1.2 manifest, even if they declare non-compliance.

4.2 v4.0 Additional Fields
----------------------------
v4.0 expanded the manifest with layer-aware and action-surface fields:

  layer       — Integer: 1 = feature, 2 = primitive, 3 = adapter/service/workflow
  requires    — Array of module IDs (v4.0 rename of "dependencies" in JS context)
  dataFiles   — Array of paths to external .json files loaded at runtime
  lifecycle   — Array of lifecycle method names (see Section 20)
  actions     — Object containing the action surface:
    commands  — Named callable functions this module exposes
    events    — Events this module emits
    accepts   — Events this module listens for
    slots     — Named content insertion points (for composition)
  backendDeps — Array of backend dependency declarations [{action, via, params}]
                (adapters only — declares which backend actions this module needs)

4.3 v5.0 Additional Fields
----------------------------
v5.0 added operational role classification and optimization targeting:

  operationalRole — System role string. Valid values:
                    registrar | captain | conductor | coach | probation-officer |
                    assembly-line | triage | savant
                    (Use "savant" for domain-expert modules with no system role.)

  optimization    — Object:
    priority      — Optimization target: speed | safety | readability | memory-footprint
    assertionSuite — Path to the test suite JSON for this module

4.4 Variant Manifest Additional Fields
----------------------------------------
Variants must also include:

  compliance  — Set to {"non-sdoa-compliant": true} if not fully compliant
  variant_of  — ID of the parent sovereign module (e.g., "Workspace.feature")

4.5 Complete v5.0 Manifest Example (JavaScript)
-------------------------------------------------
  static MANIFEST = {
    // Identity
    id:              "MathSolver.engine",
    type:            "engine",
    layer:           3,
    runtime:         "Rust",
    version:         "5.0.0",
    operationalRole: "savant",

    // Dependencies
    requires:        [],
    dataFiles:       [],
    lifecycle:       ["init", "run", "dispose"],

    // Action Surface
    actions: {
      commands: {
        transform: {
          description: "Executes vectorized floating-point matrix transformations.",
          input:  { matrix: "array" },
          output: "array"
        }
      },
      events:  {},
      accepts: {},
      slots:   {}
    },

    // Optimization
    optimization: {
      priority:       "speed",
      assertionSuite: "MathSolver.tests.json"
    },

    // Documentation
    docs: {
      description: "High-performance Rust execution unit.",
      author:      "ProtoAI Core Architecture Group",
      sdoa:        "5.0.0"
    }
  };

--------------------------------------------------------------------------------
SECTION 5 — MODULE TYPES
--------------------------------------------------------------------------------

| Type        | Layer | File Suffix        | Description                                    |
|-------------|-------|--------------------|------------------------------------------------|
| primitive   |   2   | .prim.js           | Generic, reusable UI atom                      |
| feature     |   1   | .feature.js        | Composes primitives to build a screen/area     |
| adapter     |   3   | .adapter.js        | Frontend IPC, state mgmt, data fetching        |
| service     |   3   | .service.js        | Cross-cutting concerns (EventBus, StateStore)  |
| workflow    |   3   | .workflow.js       | Backend operation — one file per operation     |
| repository  |   3   | .repository.js     | Data persistence (file system, database)       |
| engine      |   3   | .engine.rs/.py/etc | High-performance computation (Rust, Python)    |

Additional v1.2 types (from base specification):
  dashboard   — Full UI page or screen
  task        — Background, scheduled, or long-running work
  validator   — Self-describing validation rules and schemas

Language selection follows a tier model:
  Rust        -> Engine types (performance-critical, system-level, IPC commands)
  Node.js     -> Service and Task types (orchestration, data transformation)
  JavaScript  -> Primitive and Feature types (browser UI, web rendering)
  Python      -> Engine/Service types (data science, ML, AST operations)
  C/C++       -> Adapter types (hardware, legacy systems, low-level drivers)

--------------------------------------------------------------------------------
SECTION 6 — v4.1 LINE-LIMIT AMENDMENT
--------------------------------------------------------------------------------

The v4.1 Line-Limit Amendment was ratified to replace the original v4.0 limits,
which were exceeded in practice by legitimately complex modules.

6.1 Per-Type Line Limits (v4.1)
---------------------------------

| Module Type | Minimum Lines | Maximum Lines | Hard Limit | Action if Exceeded        |
|-------------|---------------|---------------|------------|---------------------------|
| Primitive   |    150        |    250        |    ~500    | Split into sub-primitives |
| Feature     |    200        |    350        |    ~500    | Extract to adapters/sub-features |
| Adapter     |    200        |    350        |    ~500    | Split by concern          |
| Workflow    |    200        |    400        |    ~500    | Extract helpers to repos  |
| Repository  |    200        |    400        |    ~500    | Split by entity type      |

Hard limit: ~500 lines. This limit is never exceeded under any circumstances.

6.2 What Triggers a Refactor
------------------------------
A file must be refactored when it:
  - Exceeds its maximum line count for its type
  - Is doing more than one thing (dual responsibility = split it)
  - Would exceed 500 lines after a planned addition

The v4.1 Amendment does not raise limits for convenience — it acknowledges that
well-organized modules in complex domains legitimately require more lines than
the original v4.0 targets. The hard limit of ~500 is inviolable.

> Note: Original v4.0 limits were: Primitive 150, Feature 200, Adapter 200,
> Workflow 200. The v4.1 Amendment supersedes these.

--------------------------------------------------------------------------------
SECTION 7 — THREE-LAYER ARCHITECTURE DETAIL
--------------------------------------------------------------------------------

7.1 Layer 1 — Features (*.feature.js)
---------------------------------------
Location: ui/features/**/

Features are complete screen areas or UI surfaces built by composing primitives
with configuration and schema data.

What a feature DOES:
  - Loads a schema from a .json file
  - Creates and configures primitive instances from that schema
  - Mounts primitives into its container element
  - Subscribes to state changes and calls primitive.update() as needed
  - Handles high-level user intent by calling adapters

What a feature does NOT do:
  - Directly create DOM elements (that is a primitive's job)
  - Call backend endpoints or IPC (that is an adapter's job)
  - Hard-code UI structure (that belongs in a schema file)
  - Exceed its v4.1 line limit

7.2 Layer 2 — Primitives (*.prim.js)
--------------------------------------
Location: ui/primitives/**/

Primitives are the smallest self-contained UI building blocks. They have no
knowledge of the application domain, no backend connections, and no hardcoded
content. They only know their configuration object.

A well-designed primitive is:
  - Generic: works in any context with different configs
  - Self-contained: owns its HTML, CSS, and behavior
  - Dumb: receives data in, emits events out, never fetches its own data
  - Slim: within the v4.1 line limits for primitives

7.3 Layer 3 — Adapters, Services, Workflows, Repositories
-----------------------------------------------------------
Location: ui/adapters/**/  (frontend adapters)
          server/workflows/**/
          server/repositories/**/
          server/services/**/

All IPC calls, data fetching, state management, and side effects live in Layer 3.
Features request data through adapters. Adapters respond with standardized
Result objects: { ok: true, data: {...} } or { ok: false, error: "message" }.

Workflow modules are standalone operations with no central dispatcher. Create the
file and the Router discovers it automatically via MANIFEST.messageType.

Repository modules handle data persistence. Workflows call repositories;
workflows never touch the file system or database directly.

--------------------------------------------------------------------------------
SECTION 8 — CANONICAL DIRECTORY STRUCTURE
--------------------------------------------------------------------------------

sdoavx/
  ui/
    tokens.css                    <- Global design tokens (colors, spacing, type)
    index.html                    <- Minimal shell (containers + script tags only)
    app.js                        <- Thin orchestrator (within line limits)
    primitives/                   <- Layer 2: Generic atoms
      Button/
        Button.prim.js
        Button.prim.css
      [one folder per primitive; CSS co-located with JS]
    features/                     <- Layer 1: Composed screens
      Chat/
        Chat.feature.js
        Chat.feature.css          <- Feature-level CSS overrides (optional)
        variants/                 <- Variants of this sovereign (see Section 15)
      [one folder per feature]
    dashboards/                   <- Full UI pages
    adapters/                     <- Frontend Layer 3
      BackendConnector.adapter.js
      StateStore.adapter.js
    services/                     <- Cross-cutting frontend services
      EventBus.service.js
    data/                         <- Externalized data (owned by consuming module)
      schemas/                    <- UI structure definitions
      catalogs/                   <- Reference data
      defaults/                   <- Default configuration values

  substrate/
    services/                     <- Infrastructure sovereigns (Node.js)
    adapters/                     <- Backend-side adapters
    bridges/                      <- Cross-language IPC bridges
    engines/                      <- Substrate-level engines
    workflows/                    <- Backend operations (auto-discovered)

  evolution/
    engines/                      <- Polyglot computation engines
      [EngineName]/
        v2/                       <- Version folders
        variants/                 <- Variants (see Section 15)
    legacy/                       <- Deprecated modules (graveyard only)
    experimental/                 <- System-level experiments only
    translations/                 <- Cross-language port versions

  authorities/
    bootstrap/                    <- System bootstrap sequences
    router/                       <- Dynamic routing config
    conductor/                    <- Event mesh management
    registrar/                    <- Module registry and manifest index
    captain/                      <- State sovereignty and lifecycle control

  documentation/
  environment/                    <- .env templates, shell scripts, docker configs,
                                     OS-level helpers, dev environment configs

Rules per directory:
  - ui/ is sovereign over all CSS, UI schemas, and UI data files
  - Binary artifacts (.bin, .wasm) live with the engine or substrate that uses them
  - JSON files live with the sovereign that consumes them (not in a global /data)
  - Scripts and environment files go in environment/
  - Rust source lives with the engine or service that defines it
  - Python source lives with the workflow or engine that defines it

PROHIBITED directories (never create these):
  /assets/, /static/, /deps/, /resources/, /misc/, /global/
  These violate sovereignty and create dumping grounds.

--------------------------------------------------------------------------------
SECTION 9 — FILE PLACEMENT RULES
--------------------------------------------------------------------------------

9.1 CSS Files
--------------
CSS belongs to UI sovereigns. Every primitive owns its co-located .prim.css file.
Features may have a co-located .feature.css file for structural overrides.
Global design tokens go in ui/tokens.css only.

  ui/primitives/Button/Button.prim.css
  ui/features/Workspace/Workspace.feature.css
  ui/tokens.css

9.2 Binary Files (.bin, .wasm, compiled artifacts)
----------------------------------------------------
Binaries belong to the engine or substrate module that consumes them.

  evolution/engines/Solvers/SolverV3/solver.wasm
  substrate/engines/wasm-runner/runner.wasm

9.3 JSON / JSN Files
---------------------
JSON files fall into three categories by ownership:

  A. Configuration JSON (authority-owned):
     authorities/registrar/registry.jsn
     authorities/router/routes.jsn

  B. Schema JSON (UI- or substrate-owned — lives with consuming module):
     ui/features/Workspace/schema.jsn
     substrate/services/Queue/schema.jsn

  C. Engine data / model metadata (evolution-owned):
     evolution/engines/TextClassifier/v2/metadata.jsn

9.4 Other Dependency Files (.txt, .cfg, .yaml, .proto)
-------------------------------------------------------
Same rule: the file lives with the sovereign that consumes it.

  substrate/bridges/grpc/messages.proto
  evolution/engines/Billing/v3/config.yaml
  ui/features/Projects/strings.json
  authorities/captain/policy.yaml

9.5 Scripts (shell, bootstrap)
--------------------------------
environment/setup.sh
environment/teardown.sh
environment/dev.env
environment/docker-compose.yaml

9.6 Rust Source
----------------
Rust files live with the engine or service that defines them, inside their
sovereign folder. The Rust layer (src-tauri/src/) is a thin transport:
  main.rs           — Tauri app setup
  commands.rs       — Registered Tauri commands
  engine_bridge.rs  — Spawns and manages the Node sidecar
  node_process_backend.rs — JSON-line IPC protocol

9.7 Python Source
------------------
Python files live with the workflow or engine sovereign that defines them.
  evolution/engines/TextClassifier/engine.py
  server/workflows/Coach.workflow.py

--------------------------------------------------------------------------------
SECTION 10 — PRIMITIVE CATALOG (19 UI Primitives)
--------------------------------------------------------------------------------

Every visual element in the application maps to exactly one primitive from this
catalog. Creating a bespoke one-off component instead of using a configured
primitive is an anti-pattern.

| Primitive   | File                  | Renders                   | Configuration Surface                              |
|-------------|----------------------|---------------------------|-----------------------------------------------------|
| Button      | Button.prim.js       | Any clickable action      | {label, icon, variant, onClick, disabled, tooltip}  |
| Input       | Input.prim.js        | Text/password/number/area | {type, label, placeholder, value, onChange, validate}|
| Toggle      | Toggle.prim.js       | On/off switches           | {label, checked, onChange}                          |
| Select      | Select.prim.js       | Dropdowns                 | {label, options, value, onChange}                   |
| Panel       | Panel.prim.js        | Any bordered content area | {title, collapsible, actions, slots}                |
| Modal       | Modal.prim.js        | Any overlay dialog        | {title, size, onClose, slots}                       |
| TabGroup    | TabGroup.prim.js     | Any tabbed interface      | {tabs:[{id,label,content}], activeTab}              |
| List        | List.prim.js         | Any scrollable list       | {items, renderItem, onSelect, emptyState}           |
| Tree        | Tree.prim.js         | Any hierarchical tree     | {nodes, onExpand, onSelect, renderNode}             |
| Form        | Form.prim.js         | Any collection of inputs  | {schema, values, onSubmit, onChange}                |
| Toast       | Toast.prim.js        | Notifications             | {message, type, duration}                           |
| Badge       | Badge.prim.js        | Status indicators, tags   | {text, variant, icon}                               |
| Toolbar     | Toolbar.prim.js      | Action bars               | {items: [Button configs]}                           |
| EmptyState  | EmptyState.prim.js   | "Nothing here" placeholders| {icon, title, hint, action}                        |
| ScrollMap   | ScrollMap.prim.js    | Minimap scrollbars        | {container, renderDot}                              |
| CodeEditor  | CodeEditor.prim.js   | Monaco wrapper            | {language, value, onChange, readOnly}               |
| ContextMenu | ContextMenu.prim.js  | Right-click menus         | {items, position}                                   |
| Spinner     | Spinner.prim.js      | Loading indicators        | {size, label}                                       |
| Markdown    | Markdown.prim.js     | Rendered markdown         | {content, allowHtml}                                |

Backend Primitives (Layer 3 Services):
  Router              Router.service.js           Reads IPC, dispatches to handlers
  WorkflowRunner      WorkflowRunner.service.js   Executes workflows with middleware
  ResponseFormatter   ResponseFormatter.service.js Standardizes all response shapes
  Logger              Logger.service.js           Structured logging with levels

--------------------------------------------------------------------------------
SECTION 11 — SDOA 3.0 ACTION SURFACE
--------------------------------------------------------------------------------

The action surface was introduced in SDOA 3.0 and is part of every v4.0+ manifest.
It enables auto-generation of system-wide command maps, event graphs, and workflow
graphs, and is the foundation of AI-driven orchestration.

11.1 Commands — "Things this module can DO on request"
-------------------------------------------------------
Callable functions that the registry can invoke. Explicitly typed and discoverable.

  commands: [
    { name: "render", description: "...", input: {}, output: "html" },
    { name: "reorder", description: "...", input: {from:"int", to:"int"}, output:"void" }
  ]

11.2 Triggers — "Things this module REACTS to"
------------------------------------------------
Events that cause the module to execute a command.

  triggers: [
    { event: "ModelAdded", action: "render" },
    { event: "ProfileChanged", action: "mapBehavior" }
  ]

(In v4.0 manifest format, triggers are represented in the actions.accepts field.)

11.3 Emits — "Things this module BROADCASTS"
---------------------------------------------
Events that other modules can listen to.

  emits: [
    { event: "InventoryUpdated", payload: { count: "int" } },
    { event: "BehaviorMapped", payload: { modelId: "string" } }
  ]

(In v4.0 manifest format, emits are represented in the actions.events field.)

11.4 Workflows — "Multi-step actions exposed externally"
---------------------------------------------------------
Higher-level operations that may call multiple commands. Enables AI orchestration.

  workflows: [
    { name: "syncInventory", steps: ["render","updateDropdowns"],
      description: "Rebuilds UI after any model change" }
  ]

What the action surface unlocks:
  - Auto-generated system-wide command map
  - Auto-generated system-wide event graph
  - Auto-generated workflow graph
  - AI-safe cross-module orchestration
  - Cross-language command routing
  - Dynamic and user-defined automation

--------------------------------------------------------------------------------
SECTION 12 — STATESTORE SPECIFICATION
--------------------------------------------------------------------------------

The StateStore replaces all scattered window.* globals with a single, centralized
reactive state store. No module reads from or writes to global variables.

File: ui/adapters/StateStore.adapter.js

API:
  get(key)              Returns the current value for a state key
  set(key, value)       Sets a value and notifies all watchers; auto-persists
                        to localStorage for configured keys
  watch(key, handler)   Subscribes to changes on a key; returns unsubscribe fn

State Flow:
  User action -> Feature.handleX()
    -> StateStore.set("someKey", newValue)
      -> StateStore notifies all watchers
        -> Feature A calls primitive.update()
        -> Feature B calls primitive.update()
        -> Adapter syncs to backend if needed

Rules:
  - Never use window.* as state. Use StateStore.set() and StateStore.get().
  - Modules subscribe in init(), unsubscribe in destroy(). Watch in init = must
    unwatch in destroy, or you leak.
  - StateStore does not call primitives directly. Features watch state and call
    their own primitives.

--------------------------------------------------------------------------------
SECTION 13 — EVENTBUS SPECIFICATION
--------------------------------------------------------------------------------

The EventBus enables pub/sub cross-module communication without direct coupling.
Modules communicate by emitting and listening to named events.

File: ui/services/EventBus.service.js

API:
  emit(event, payload)    Broadcasts an event to all listeners
  on(event, handler)      Subscribes to an event; returns unsubscribe fn

Event naming convention: "module:action" (e.g., "backend:statusChanged")

Rules:
  - Modules register event listeners in init(), remove them in destroy().
  - Event names must follow the module:action convention.
  - Circular event dependencies are prohibited (same rule as module dependencies).

--------------------------------------------------------------------------------
SECTION 14 — BACKENDCONNECTOR AUTO-ROUTING SPECIFICATION
--------------------------------------------------------------------------------

The BackendConnector adapter replaces manual switch statements with declaration-
based routing. It reads backendDeps from all loaded module manifests and builds
its routing table automatically.

File: ui/adapters/BackendConnector.adapter.js

How it works:
  1. During init(), scans all module MANIFEST.backendDeps arrays
  2. Builds a routing table: action -> {via, params, module}
  3. On dispatch(action, payload), looks up the route and invokes the correct
     Tauri command
  4. Falls back to engine_ipc passthrough for unknown actions

Adding a new backend route:
  Add a backendDeps entry to the relevant module manifest. No changes to
  BackendConnector required.

Server-side: Router.service.js consumes JSON-lines over stdin, converts the
incoming msgType to a PascalCase workflow ID, and dispatches to the matching
*.workflow.js module found in the registry.

Adding a new workflow: Create one file. Dynamic routing delegates automatically.
No manual switch statements or registration steps.

Standardized response shape (every backend operation returns this):
  { ok: true, data: { ... } }    // Success
  { ok: false, error: "..." }    // Failure

--------------------------------------------------------------------------------
SECTION 15 — VARIANT POLICY
--------------------------------------------------------------------------------

15.1 Definition
----------------
A variant is an alternate implementation of a sovereign module. Variants are
branches, not versions. They are not the same as version increments.

15.2 Placement Rule
--------------------
Every variant lives inside the parent sovereign's variants/ subdirectory.
Variants NEVER go in /legacy/, /experimental/, /global/, or /misc/ unless the
variant has been fully deprecated and removed from the active registry.

  ui/features/Workspace/
    Workspace.feature.js         <- canonical sovereign
    variants/
      compact/
        manifest.jsn
        Workspace.compact.feature.js
      mobile/
        manifest.jsn
        Workspace.mobile.feature.js

15.3 Manifest Requirements
---------------------------
Every variant must have a full SDOA v1.2 Manifest including:
  id          — unique, e.g. "Workspace.feature.compact"
  type        — same type as parent (feature, service, engine, etc.)
  version     — variant's own version, independent of parent
  runtime     — execution environment
  capabilities — what this variant provides
  dependencies — what it needs
  docs        — description of what makes this variant different
  last_modified — ISO 8601 timestamp
  compliance   — "non-sdoa-compliant": true if needed
  variant_of  — ID of the parent sovereign (e.g., "Workspace.feature")

Example variant manifest:
  {
    "id": "Workspace.feature.compact",
    "type": "feature",
    "version": "1.0.0",
    "runtime": "js",
    "variant_of": "Workspace.feature",
    "capabilities": ["ui:workspace:compact"],
    "dependencies": [],
    "docs": "Compact variant optimized for small screens.",
    "last_modified": "2026-06-17T15:14:00Z"
  }

15.4 Deduplication Policy
--------------------------
Same name + same extension = variants of the same sovereign.
  -> Keep the newest as canonical. Move the older to variants/.
Same name + same extension + same file size = exact duplicate.
  -> Delete the duplicate.

15.5 When a File Becomes a Variant vs. Canonical
--------------------------------------------------
A file is a variant (not a new sovereign) when it fulfills the same functional
contract as an existing sovereign but with a different implementation approach,
optimization target, or deployment context.

--------------------------------------------------------------------------------
SECTION 16 — IMPLEMENTATION PROTOCOL GATES
--------------------------------------------------------------------------------

The five Implementation Protocol Gates govern how SDOA work is performed in
practice — not just how code is structured.

Gate 1 — Pending State for Ambiguous Input
  When files are provided without accompanying instructions, enter a Pending
  state and wait for an explicit instruction signal. Do not act on assumptions.

Gate 2 — Atomic File Delivery
  All code modifications must be delivered as complete source files. Partial
  snippets are prohibited. A complete file is always safe to drop in; a partial
  file can break module discovery.

Gate 3 — Temporal Metadata Headers
  Every file must begin with a standardized header:

  // ------------------------------------------------------------------
  // File:    Button.prim.js
  // Version: 1.0.05
  // Updated: 2026-05-04T14:32:00Z
  // Changes: Added loading variant; fixed disabled state cursor
  // ------------------------------------------------------------------

  This header is the audit trail for every file in the system.

Gate 4 — Micro-Incrementation
  Every alteration to a file requires a version increment. Use three-part
  versioning (major.minor.patch) where patch increments on every change
  (e.g., 1.0.04 -> 1.0.05). This creates a dense audit trail.

Gate 5 — Declarative Compliance
  Before writing any code, verify architectural placement. Does this module
  comply with its layer rules? Does it declare all dependencies? Does it follow
  the lifecycle contract? Fix the architecture first, then write the code.

--------------------------------------------------------------------------------
SECTION 17 — ANTI-PATTERNS REFERENCE
--------------------------------------------------------------------------------

The following patterns are prohibited in SDOA. The v5.0 ProbationOfficer
sovereign automatically rejects files that introduce these patterns.

| PROHIBITED                                    | SDOA REPLACEMENT                                    |
|-----------------------------------------------|-----------------------------------------------------|
| window.currentProject = ...                   | StateStore.set("currentProject", ...)               |
| Manual switch/case in a dispatcher            | Auto-routing from MANIFEST.messageType              |
| Hard-coded HTML in app shell                  | Schema-driven rendering via Form/Panel/Modal prims  |
| Files over hard line limit                    | Split into primitive + feature + adapter            |
| CSS in one giant file                         | Co-located .prim.css per primitive + tokens.css     |
| document.createElement throughout features   | Primitive's mount(container) lifecycle method       |
| Direct window.__TAURI__.invoke()              | BackendConnector.dispatch(action, payload)          |
| Hardcoded model lists in JavaScript           | models.catalog.json loaded at runtime               |
| setTimeout(init, 500) hacks                   | Proper async init() with await and lifecycle order  |
| One-off bespoke components per screen         | Configured instances of generic primitives          |
| State in local component variables            | StateStore.get() / .set() / .watch()                |
| Event listeners never removed                 | unmount() cleans up everything mount() did          |
| Cross-language direct imports                 | Declarative manifest requires[] via Registrar       |
| Global namespace pollution                    | StateStore interface only                           |
| Monolithic files past hard limit              | Decompose per v4.1 Amendment                        |
| setTimeout catch hacks                        | Lifecycle-managed async with Captain for state      |
| /assets/, /static/, /deps/, /resources/ dirs | Sovereignty-based placement (see Section 9)         |

--------------------------------------------------------------------------------
SECTION 18 — MIGRATION SEQUENCE (PHASES 0-9)
--------------------------------------------------------------------------------

The migration from monolithic v3 to SDOA v4/v5 follows nine phases. The app
must remain functional after every phase. Phase N+1 does not begin until Phase N
is verified working.

Current State (at time of documentation):
  app.js            833 lines  — God-object; must be decomposed
  server-ipc.cjs    778 lines  — Monolithic dispatcher with manual switch
  Settings.ui.js    965 lines  — One-off modal/tabs/form/save logic
  styles.css      2,160 lines  — Monolithic; no tokens, no scoping

Phase 0 — Skeleton & Foundation
  Create v4 directory structure. Write tokens.css. Write StateStore.
  Create ModuleLoader.service.js. Do NOT change any existing code.

Phase 1 — Core Primitives
  Build the 8 most-reused primitives:
  1a. Button.prim.js
  1b. Input.prim.js
  1c. Panel.prim.js
  1d. Modal.prim.js
  1e. TabGroup.prim.js
  1f. List.prim.js
  1g. Form.prim.js
  1h. Toast.prim.js

Phase 2 — StateStore & BackendConnector v4
  Replace window.* globals with StateStore. Replace manual switch routing
  with auto-discovery. Upgrade EventBus with lifecycle awareness.

Phase 3 — Settings Migration (Proof of Concept)
  Migrate Settings.ui.js (965 lines) to Settings.feature.js (~100 lines)
  plus JSON schemas (~200 lines). Remove all hand-coded Settings HTML from
  index.html. Verify end-to-end before proceeding.

Phase 4 — Feature Migrations
  4a. Chat Feature (from app.js)
  4b. FileExplorer Feature (FileManager + FileTree + FileList + ManifestPanel)
  4c. ProjectManager Feature
  4d. ModelManager Feature (externalize archetype catalog)
  4e. app.js Slim-Down (target: ~80 lines)

Phase 5 — Backend Decomposition
  Replace server-ipc.cjs (778 lines) with auto-discovering Router.
  Create Router.service.js, Middleware.service.js, ResponseFormatter.service.js.
  Convert all handlers to *.workflow.js files with v4 manifests.

Phase 6 — Data Externalization
  Move all embedded datasets to JSON files:
    Model catalog -> ui/data/catalogs/models.catalog.json
    Archetypes   -> ui/data/catalogs/archetypes.catalog.json
    Extensions   -> ui/data/catalogs/extensions.catalog.json
    Settings defaults -> ui/data/defaults/settings.defaults.json
    Policy defaults   -> ui/data/defaults/policy.defaults.json

Phase 7 — CSS Extraction
  Extract tokens.css from styles.css.
  Co-locate each primitive's CSS with its JavaScript.
  Update load order: tokens -> primitives -> features.

Phase 8 — Feature Roadmap (Prior Plans Integrated)
  11 sub-features, each independently shippable:
  8a. Intelligence Expansion — Memory & User Profiling
  8b. Silent Partner — Persona Dialogue
  8c. Google Drive Integration
  8d. VFS Tier System (Eager/Cached/Lazy Context Control)
  8e. Bun Runtime Provisioning (rename only)
  8f. Multi-Session Chat UI
  8g. Browser & Terminal Tabs
  8h. Archetype & Hybrid Profile System
  8i. QMD Semantic Search & Indexing
  8j. Response Caching
  8k. System Prompt Injection (Project Rules)

Phase 9 — Infrastructure & Quality of Life
  9a. Error Mapping & Actionable Traces
  9b. Token Usage Monitoring
  9c. History Compaction
  9d. Encrypted Vault for API Keys

Prior Plans Cross-Reference (14 items):
  implementation_plan.md — File Manager Redesign           (-> Phase 4b)
  implementation_plan_intelligence.md — Memory & Profiling (-> Phase 8a+8b)
  implementation_plan_intelligence.md — Silent Partner     (-> Phase 8b)
  implementation_plan_intelligence.md — Tools & Real-time  (-> Phase 8)
  google_drive_plan.md — Google Drive                      (-> Phase 8c)
  analysis_results.md — VFS Tier System                    (-> Phase 8d)
  analysis_results.md — Archetype & Hybrid Profiles        (-> Phase 8h)
  analysis_results.md — Response Caching                   (-> Phase 8j)
  handoff_report.md — Multi-Session Chat UI                (-> Phase 8f)
  handoff_report.md — Browser & Terminal Tabs              (-> Phase 8g)
  handoff_report.md — System Prompt Injection              (-> Phase 8k)
  handoff_report.md — Sidebar Filtering                    (-> Phase 4c)
  SysProvisionBunWorkflow.js — Bun Runtime                 (-> Phase 8e)
  QmdAdapter.js / IngestWorkflow.js — Semantic Search      (-> Phase 8i)

--------------------------------------------------------------------------------
SECTION 19 — FILE HEADER FORMAT
--------------------------------------------------------------------------------

Every SDOA file must begin with a standardized header block. This is Gate 3 of
the Implementation Protocol and is mandatory on all files.

JavaScript / TypeScript / Node.js:
  // ------------------------------------------------------------------
  // File:    [Filename.type.js]
  // Version: [major.minor.patch]
  // Updated: [ISO 8601 timestamp]
  // Changes: [Description of what changed]
  // ------------------------------------------------------------------

The header serves as the audit trail. It must be updated on every change
alongside the version increment (Gate 4 — Micro-Incrementation).

--------------------------------------------------------------------------------
SECTION 20 — LIFECYCLE CONTRACTS
--------------------------------------------------------------------------------

20.1 Frontend Lifecycle (Primitives and Features)
---------------------------------------------------
Every UI module MUST implement all five methods in order:

  async init(config)       Called once when the module is first loaded.
                           Register event listeners, load data files.
                           Do NOT touch the DOM here.

  async mount(container)   Called when the module's DOM is attached to the page.
                           Render initial state. Receives the container element.

  async update(newState)   Called when state changes affect this module.
                           Re-render only what changed. Avoid full re-renders.

  async unmount()          Called when the module's DOM is removed.
                           Remove event listeners, cancel pending requests.
                           Must undo everything done in mount().

  async destroy()          Called once when permanently destroyed.
                           Final cleanup — release memory, close connections.
                           Must undo everything done in init().

Common lifecycle mistakes:
  - Calling mount() before init()
  - Forgetting to remove event listeners in unmount()
  - Doing DOM work in init() (the container does not exist yet)
  - Calling destroy() without first calling unmount()

20.2 Backend Lifecycle (Workflows, Repositories)
--------------------------------------------------
Backend modules implement a simpler three-method contract:

  async init(registry)    Called once at server startup.
                          Register self, load dependencies.

  async run(payload)      Called per-request.
                          Execute the operation. Return { ok, data/error }.

  async dispose()         Called at server shutdown.
                          Cleanup — close connections, release resources.

--------------------------------------------------------------------------------
SECTION 21 — COMPLIANCE CHECKLIST
--------------------------------------------------------------------------------

Use this checklist before marking any module complete.

Identity & Manifest:
  [ ] Module has a MANIFEST block at the top of the file
  [ ] id is unique across the entire system
  [ ] type is one of the valid module types
  [ ] layer is correct (1, 2, or 3)
  [ ] runtime is declared
  [ ] version is set
  [ ] docs.description is populated
  [ ] last_modified is updated
  [ ] All v1.2 mandatory fields are present

Layer Compliance:
  [ ] Features only call primitives (not adapters directly)
  [ ] Primitives only emit events (never call adapters)
  [ ] Adapters are only called from features
  [ ] No circular dependencies

Lifecycle:
  [ ] All five frontend lifecycle methods are implemented (if UI module)
  [ ] All three backend lifecycle methods are implemented (if backend module)
  [ ] Event listeners registered in init() are removed in destroy()
  [ ] DOM work is only done in mount() and update()

File Size (v4.1 Amendment):
  [ ] Line count is within the type-appropriate range
  [ ] Line count does not exceed the hard limit (~500 lines)

File Header:
  [ ] Header block is present at top of file
  [ ] Version in header matches MANIFEST.version
  [ ] Updated timestamp is current
  [ ] Changes field is populated

Placement:
  [ ] File is in the correct canonical directory
  [ ] CSS is co-located with its primitive
  [ ] Data files are owned by the sovereign that consumes them
  [ ] Variants are in the parent sovereign's variants/ subdirectory
  [ ] No prohibited directories are created (/assets/, /static/, etc.)

================================================================================
END OF SDOA WHITEPAPER — TECHNICAL EDITION v5.0
================================================================================
