ADR-0001 — Plugin-first architecture¶
Status: 🚫 Superseded
Date: (original, undated — carried over from Applejack_Framework_Docs/)
Supersedes: —
Superseded by: ADR-0002 — Module architecture
This ADR is no longer in force. It is preserved because the reasoning behind it is sound and because a future contributor will otherwise propose it again. Read ADR-0002 for the decision that replaced it, including a fair statement of what this one got right.
Original text¶
The original record, reproduced in full and unedited:
ADR-0001 Plugin First¶
Accepted.
All gameplay is implemented as plugins.
Accompanying commitments from the same documentation set
(00_PROJECT_CONSTITUTION.md, 03_PLUGIN_SYSTEM.md):
- Core hosts plugins only; gameplay exists only in plugins.
- Lifecycle: Discover → Validate → Load Config → Register Services → Register Components → Ready → Shutdown.
- Manifest fields: Name, Version, Dependencies, Capabilities, Assets, Config schema.
- Plugins depend on Core interfaces only, and on other plugins only via published interfaces or events.
- Character, Inventory and Economy are first-party plugins, used to prove the SDK.
Why it was superseded¶
Summarised here; argued in full in ADR-0002.
-
The machinery is the project. Discovery, manifest parsing, validation, version resolution, dependency ordering, isolation and hot-reload are months of work that produce no gameplay, and must be right before anything else can be built on them.
-
S&box already provides most of it. Hot reload is built in, and the Libraries system is the engine's supported answer to distributing self-contained reusable code and assets. A bespoke loader reimplements engine features less well.
-
The legacy evidence points elsewhere. Applejack's modularity came from where its boundaries were drawn — policy, needs, map data and cosmetics as separate units — not from its loader, which is 98 lines and the source of several defects (D-07, D-08). Its worst coupling arose because plugins were a separate lifecycle that items and jobs had to interrogate at load time.
-
It answers the wrong question. The goal is third-party extensibility. That is served by stable interfaces, typed events and documented extension points — not by making first-party code pretend to be third-party.
What survives from it¶
ADR-0002 keeps the parts that were right, and they are most of it:
- Hard module boundaries with a declared dependency direction.
- Modules communicate only through registered service interfaces and published events.
- An explicit, deterministic lifecycle.
- Failure isolation, so one broken unit does not take down the server.
- Character, Inventory and Economy built against the same public surface a third party would use — the discipline of "dogfood the extension API" is retained, without the loader.