ARCH-01 clean-break target-state decision
This is a reference decision record for issue #1533 and epic #1532.
Quick orientation
- Read this if: you need the long-lived decision behind the target package graph.
- Skip this if: you only need the canonical package layout and contributor rules; use Target-state package graph.
- Go deeper: use Architecture overview for the current system map and Gateway for runtime mechanics.
Decision snapshot
Tyrum uses a clean-break target package graph built around contracts, transport, node, operator-app, focused runtime packages, and a reduced gateway composition root.
Decision
- Adopt
@tyrum/contractsas the only shared contract package. - Split typed transport into
@tyrum/transport-sdkand generic node lifecycle into@tyrum/node-sdk. - Keep
@tyrum/operator-appas the shared operator state/action surface and@tyrum/operator-uias the operator UI surface on top of it. - Extract runtime and business logic into
@tyrum/runtime-policy,@tyrum/runtime-node-control,@tyrum/runtime-execution,@tyrum/runtime-agent, and@tyrum/runtime-workboard. - Reduce
@tyrum/gatewayto composition root, transport adapters, bootstrap, and bundled operator asset serving.
Why this decision
- The historical package graph let transport and runtime concerns leak upward into operator code.
- The clean-break target package graph makes dependency directions explicit enough for CI checks and contributor review.
Non-negotiable rules
- No backwards-compatibility shims.
- When one runtime package needs another, the dependency goes through explicit ports and interfaces rather than gateway internals.
Consequences
- Contributor entry points and PR templates need to point to the target package graph so new work reinforces the current shape.
- The package-boundary CI gate in
#1534should encode this decision rather than invent a second architecture source of truth. Keepscripts/lint/package-boundaries.config.mjssynchronized with this record and with Target-state package graph. - Inside
@tyrum/gateway, route and WebSocket entrypoints now depend onpackages/gateway/src/app/**seams sopackages/gateway/src/modules/**stays behind an explicit internal boundary.