Architecture Boundaries

July 2, 2026 ยท View on GitHub

Lemon enforces direct umbrella dependencies by app. This keeps the harness modular and prevents layer drift.

Direct Dependency Policy

AppAllowed direct umbrella deps

| agent_core | ai, lemon_core | | ai | (none) | | coding_agent | agent_core, ai, lemon_browser, lemon_core, lemon_skills | | coding_agent_ui | coding_agent | | lemon_automation | lemon_core, lemon_router, lemon_skills | | lemon_browser | lemon_core | | lemon_channels | agent_core, lemon_core, lemon_media, x_api | | lemon_cli | ai, lemon_core | | lemon_control_plane | agent_core, ai, coding_agent, lemon_automation, lemon_browser, lemon_channels, lemon_core, lemon_lsp, lemon_media, lemon_router, lemon_skills | | lemon_core | (none) | | lemon_evals | agent_core, ai, coding_agent, lemon_core, lemon_skills | | lemon_gateway | agent_core, ai, coding_agent, lemon_automation, lemon_core | | lemon_lsp | lemon_core | | lemon_mcp | agent_core, coding_agent, lemon_skills | | lemon_media | lemon_core | | lemon_router | agent_core, ai, lemon_channels, lemon_core, lemon_media | | lemon_sim | agent_core, ai, lemon_core | | lemon_sim_ui | ai, lemon_core, lemon_sim | | lemon_skills | agent_core, ai, lemon_core, lemon_media, x_api | | lemon_web | lemon_core, lemon_router | | x_api | lemon_core |

Enforcement

Run:

mix lemon.quality

The architecture checker enforces both:

  • direct umbrella dependencies from apps/*/mix.exs
  • namespace references in apps/*/lib/**/*.ex (forbidden cross-app module usage)

It fails if any app introduces either an out-of-policy direct dependency or an out-of-policy cross-app namespace reference. It also reports non-failing target-policy drift for transitional dependencies that should be removed by the active review remediation milestones.

Runtime Ownership Rules

The refactor quality rules also enforce a few concrete ownership boundaries:

  • lemon_router may emit semantic LemonCore.DeliveryIntent values, but it may not construct LemonChannels.OutboundPayload values or reference Telegram renderer helpers directly.
  • Automation-origin channel notifications may use LemonRouter.ChannelsDelivery as a narrow bridge into LemonChannels, but this must not become a router-owned rendering path. Router code must continue to avoid OutboundPayload construction and platform renderer helpers.
  • lemon_channels owns channel rendering and presentation state. It must not mutate inbound prompts for pending-compaction behavior.
  • lemon_gateway owns execution slots and engine lifecycle. Router-owned queue semantics, chat-state readback for auto-resume request mutation, and conversation-key selection must not move back into gateway. Router hands pre-resolved LemonCore.ExecutionCommand values to the configured LemonCore.EngineRuntime; LemonGateway.ExecutionRequest is gateway-private adapter state, and LemonGateway.Runtime.submit/1 must not be reintroduced as a legacy compatibility path. Default gateway startup is execution-only; gateway-native transport, command, SMS, and voice children are transitional legacy ingress and require explicit :legacy_ingress_enabled configuration.
  • Gateway-owned transports submit through LemonCore.RouterBridge when they need router normalization. They must not take a compile-time dependency on LemonRouter.RunOrchestrator.
  • Router-owned active session state is only exposed through LemonRouter.Router and LemonCore.RouterBridge. External apps must not reference LemonRouter.SessionRegistry or LemonRouter.SessionReadModel directly.
  • Router and channels should validate engine IDs through LemonCore.EngineCatalog. Router should use LemonCore.Cwd for default cwd resolution instead of LemonGateway.Cwd.
  • Shared domains in lemon_core / lemon_control_plane must use typed wrappers such as RunStore, ChatStateStore, PolicyStore, and ProjectBindingStore instead of bypassing them with raw store helpers.

Run mix lemon.quality after boundary changes. It now checks both dependency policy and these architecture guardrails.

Skill Source Taxonomy

Skills are classified by source kind. New source kinds must be added here before being used in code. Trust levels are frozen; the set may only be extended via a documented invariant update.

Source Kinds

Source kindDescriptionExample identifier
builtinBundled with the Lemon release. Never fetched from the network.builtin/commit-guide
localA directory on the local filesystem outside the installation./path/to/my-skill
gitA git repository cloned by URL.https://github.com/user/skill-repo
registryAn entry from the official Lemon skill registry, addressed by namespace path.official/devops/k8s-rollout
well_knownA curated community source with a stable short identifier (e.g. GitHub user/repo shorthand).gh:user/skill-repo

Trust Levels

Trust levels control install/update policy and audit behavior. Ordered from highest to lowest trust:

Trust levelAssigned toPolicy
builtinSource kind builtin only.No audit required. Cannot be uninstalled.
officialSkills in the official/ registry namespace.Audit runs; warn verdicts require acknowledgement; block verdicts cannot be overridden.
trustedSources explicitly added to the user's trusted list.Same audit policy as official.
communityAll other git, registry, and well_known sources not in the trusted list.Audit runs; warn verdicts require explicit approval; block verdicts cannot be overridden.

local skills inherit the trust level of the install scope (builtin for bundled seeds, trusted when explicitly added by the user, community otherwise).

Module Placement Rules

These rules complement the dependency policy table above. They must be respected when adding new modules.

DomainCanonical homeForbidden locations
Memory scope stores (session, workspace, agent, global)lemon_coreAny other app
Browser capability driverlemon_browserlemon_core, coding_agent, lemon_control_plane
Media job driverlemon_medialemon_core, lemon_skills, lemon_router, lemon_control_plane
LSP server driverlemon_lsplemon_core, coding_agent, lemon_control_plane
Skill platform logic (manifest, registry, installer, lockfile, source router, audit)lemon_skillscoding_agent, lemon_core, lemon_router
Prompt assembly and tool registrationcoding_agentlemon_skills, lemon_core
Model/session routinglemon_routercoding_agent, lemon_skills
Runtime boot, profile, health, env detectionlemon_core/runtimeShell scripts (only thin wrappers allowed there)

When a new module does not fit an existing domain, update this table before adding the module.