Skip to content

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.