muster

Ports: swap the system, keep the core

Muster talks to four kinds of outside system: an issue tracker, a code forge, a model provider and an agent runtime. Each sits behind a small interface. The core sees only the interface, never a vendor client or a wire format.

The core, the ports and the adapters

muster coreroll and bridge: no vendor codeissue trackersmall interfaceLinearyour adapterswap incode forgesmall interfaceGitHubyour adapterswap inmodel providersmall interfaceOpenRouteryour adapterswap inagent runtimesmall interfacepi processyour adapterswap in muster coreno vendor codeissue trackerinterfaceLinearor your owncode forgeinterfaceGitHubor your ownmodel providerinterfaceOpenRouteror your ownagent runtimeinterfacepi processor your own
Solid boxes are adapters that exist today. Dashed boxes show where another adapter goes.

Swapping one tracker or forge for another means writing one adapter and a fake. The reducer and the tables do not change.

The contract, in plain words

bridge: the pure coreports: interfaces and adapterssignalman, bosun, tally
A test enforces the import rules, and no package imports the command package.

What an adapter provides

How a new adapter is added and tested

1 define the interface2 write the adapter3 write the fake4 test both on the same cases5 add the import rule row
The adapter and its fake are tested against the same cases.

The tests of the signalman, bosun and tally use the fakes, so they run fast, offline and the same way every time.

Webhooks in, API reads to check

The tracker and the forge send webhooks, and the gangway verifies, dedupes and records each one. The tally reads the tracker and the forge through the ports when a row is older than a set time, and records what it finds as events. A caller never decides from a stale row.

tracker, forgeportswebhooksAPI readsgangwaytallyroll
Webhooks first, and API reads by the tally to check the record.

Where the ports are going

Direction. Everything in this section comes from designs the owner has approved. It is planned, and none of it is shipped.

One contract and a conformance suite

A small kit will give every port one shape: describe, health and close, six typed errors and a registry. A contract suite will run against every registered port and every fake. Core packages will import only the kit and the kind packages, so deleting an adapter directory leaves the build and the core tests green. Vendor names will stay inside their own adapter directory, and the inspect command will go red when one leaks.

A second forge adapter, Gitea, will prove it: one directory, one settings block and one registration line, with no core file changed. An authoring guide, with a skeleton that compiles, will let someone who has never seen the code add a port.

Webhooks with API fallback on every port that listens

Each instance of a port that receives vendor events will be set to one of three modes. In webhook mode the vendor pushes, and a reconcile pass still finds anything missed. In poll mode Muster reads the vendor on a cursor and serves no inbound route. In auto mode the webhook is primary, Muster falls back to polling when the channel goes silent or fails, and it returns after clean checks. You can set any mode at any time, in settings or with one command, with no restart.

The kit will own signature checks, replay and duplicate defence, ordering and the poller, so no adapter writes them. Delivery will be at least once, with duplicates dropped. The forge and the tracker will support these modes. The model provider and the agent runtime have no inbound events and need none.

A secrets port

Secrets will become a port too. It will give versioned reads and rotation without a restart. Files stay the default store, and Vault will be the first remote store. The port will keep the last good value for a bounded age, pause new work when the store is down, and never put a secret value in a log, an event, an error, a settings page or the audit log. One test will plant a marker secret and scan all of them.

The same design leads to per consumer provider keys, so each consumer holds its own key with its own limits.

Pluggable skiff backends

A six method backend interface, a registry and a router will let several backends run at once. The router uses fixed field rules and the first match wins. Local hosts and Kubernetes come first, in the tree. A driver protocol, a versioned JSON exchange with an external program, will add a cloud with no Muster code. Backend credentials will be references to files in the secrets directory. The seat protocol, the lease and the run credential do not change, and one run never spans two backends.

Licensing

Muster is Apache 2.0 today. The plan adds a contributor agreement with a bot gate, a trademark policy and a licence check on dependencies, so the project stays open to outside contribution.

Port by adapter by status

PortAdapterStatusWhat it does
Issue trackerLinearShippedreads issues by state; comments and state writes with an idempotency key; creates issues; sets the delegate of a ticket and writes agent sessions
Code forgeGitHubShippedreads the repository, pull requests, CI runs and one file; the head of the default branch
Model providerOpenRouterShippedreads key information
Agent runtimepi, as an operating system processShippedstarts a process from a spec, waits for its exit, stops it and its children
Shared HTTP clienthttpkitShippedtimeout, retry with jitter, Retry-After, ETag cache, request budget
Code forgeGiteaPlanneda second forge, to prove the contract with one directory and one registration line
Tracker and forgewebhook, poll and auto modesPlannedwebhooks with API fallback, set for each port instance
Secretsfile store and VaultPlannedversioned reads and rotation without a restart
Skiff backendspool, local, Kubernetes, exec driverPlannedseveral backends live at once, chosen by a router
Notifierto be chosenPlanneda fifth kind of port
Every portrequest quota for each decision classPlanneda budget per class, not only per client

Shipped means merged and working. Planned means approved in a design, with the build ahead.