How it works¶
This page explains the architecture for people who want to know why the plugin behaves the way it does. You don't need to read it to use the plugin.
One plugin, many organisations¶
Every organisation in the EMPN network installs the same canonical plugin from the same GitHub repository. The differentiation — voice, themes, visuals, source tiers, folder conventions — lives in a per-organisation overlay folder inside the plugin.
flowchart LR
R[EMPN-eu/empn-core<br/>GitHub repo] --> C[Cowork sync]
C --> A[Arena Idé<br/>install]
C --> D[Dezernat Zukunft<br/>install]
C --> I[Institut Avant-Garde<br/>install]
C --> E[EMPN<br/>install]
A -->|EMPN_ORG=arena-ide| O1[arena-ide overlay]
D -->|EMPN_ORG=dezernat-zukunft| O2[dezernat-zukunft overlay]
I -->|EMPN_ORG=institut-avant-garde| O3[institut-avant-garde overlay]
E -->|EMPN_ORG=empn| O4[empn overlay]
Same skills run everywhere. Outputs differ because the shared docs they load resolve through the active overlay.
The lookup chain¶
When a skill needs a shared doc — house style, themes list, design tokens, folder conventions, anything — it loads shared/<topic> and the resolver walks three layers in order:
shared/<EMPN_ORG>/<topic> ← partner override (if exists)
shared/_common/<topic> ← universal rules
shared/empn/<topic> ← canonical reference + default fallback
First match wins. A partner overlay is sparse by design: it only contains files the partner wants to differ from EMPN's defaults. Everything else falls through.
flowchart LR
Skill["skill calls<br/>shared/house-style.md"] --> Resolver{lookup<br/>chain}
Resolver -->|exists?| Partner["shared/<EMPN_ORG>/<br/>house-style.md"]
Resolver -->|exists?| Common["shared/_common/<br/>house-style.md"]
Resolver -->|fallback| Empn["shared/empn/<br/>house-style.md"]
Partner --> Return["return file"]
Common --> Return
Empn --> Return
A partner with no override gets EMPN-branded outputs on Day 1 — a working starting point, not an empty one.
What goes where¶
| Layer | What lives there | Examples |
|---|---|---|
_common/ |
Universal across the network — methodology that doesn't change per org | anti-ai-tone.md, search-pattern.md, monitor-pattern.md, eu-legislation-process.md, themes/energy/data-tiers.md |
empn/ |
EMPN's identity, also the default fallback for partners who don't override | house-style.md, themes.md, folder-conventions.md, org-identity.md, visuals/, narrative-arc.md |
<partner>/ |
A partner's overrides — sparse | Usually org-identity.md, visuals/, themes.md, sometimes house-style.md |
For the file-by-file split, see Folder structure.
The resolver itself¶
shared/scripts/overlay_setup.py runs once at install time and after each plugin update. It:
- Reads
EMPN_ORGfrom the environment (or the workspace-level.empn-orgmarker file, which takes precedence if present). - Validates the value against
shared/_orgs.yaml. Refuses unregistered slugs with a clear error — no silent fallback toempn, because silent fallback is how partners would ship EMPN branding by accident. - Walks the lookup chain for every canonical path under
shared/and creates symlinks at the canonical names (shared/house-style.md,shared/themes.md,shared/visuals/, etc.).
Skills read shared docs via standard markdown links — [house style](../../shared/house-style.md) — the same pattern they used before the multi-org refactor. The model never picks the org; the symlink does.
This matters because the resolution is deterministic at the OS layer, not at the prompt-interpretation layer. A model can miss a marker file or hallucinate a path. A symlink either resolves or 404s.
Why an overlay model instead of forking¶
The obvious alternative is "every partner forks the repo." That fails in two ways for this audience:
- Most partner contacts don't maintain a git fork comfortably. Pulling upstream changes into a forked
shared/runs into merge conflicts the first time, and never gets fixed. - Improvements to the universal layer (search patterns, EU process docs) should propagate to everyone automatically. A fork puts that propagation behind a manual rebase.
The overlay model keeps one canonical repo. Partners contribute back via PR — registering their slug, adding their overlay folder, suggesting improvements to _common/. Same model, less drift.
Contributing back¶
Partners and EMPN members contribute via PRs on EMPN-eu/empn-core. The contract:
- Universal improvements (better source-tier rules, new editorial patterns, a missing EU institution) go in
_common/. PR review checks the rule is universal. - Identity changes (your logos, your themes, your blurb) go in your own overlay folder. PR review makes sure changes don't leak into other installs.
- New skills must be universal by construction. Org-specific behaviour belongs in
shared/scripts/keyed offEMPN_ORG, not in a skill body.
See Contributing for the full conventions.
Reference¶
tools/multi-org-refactor-plan.md— the full architectural reasoning, including the slug convention and the decision history.plugins/empn-core/shared/scripts/overlay_setup.py— the resolver source.plugins/empn-core/shared/_orgs.yaml— the allow-list of registered organisations.