Context
A member changes code or assets that it does not own in several ways: it restyles a package’s screen, renames a package’s text, moves a dashboard widget, or swaps a placement. Today those changes sit in different places:assets/overrides/ folders for files, <name>.override.tsx files for renderers, and Widget.place declarations
beside the host. A reviewer has to search each place on every package upgrade. The v3 model also gives a
module’s override a class name that carries the host’s prefix, which hides the base class.
This ADR puts every such change in one tree, makes a shadow the file at the same path, and states the order
in which placements replace one another. The naming of an override class follows ADR 0305 (rule 1).
Decision
One tree.- Everything that changes code or assets the member does not own lives in one tree,
src/overrides/<owner>/, which mirrors the owner’s own paths. The<owner>is the package name with its scope, for example@acme/loyalty-kit, or<service>/<module>for a consumed service module. The rest of the path is the owner’s path from its root. - A file in the tree shadows the file at the same path in the owner. No keyword and no
.override.tsxsuffix are used. A component shadow issrc/overrides/@acme/loyalty-kit/src/react/points-balance/points-balance.tsx, for example. - The scattered
assets/overrides/folders are retired. Their files move into the tree at their owner’s path. The.override.tsxsuffix of ADR 0294 decision 14 is retired with them. - Language files merge key by key over the owner’s file, so a shadow of
orders.jsonchanges only the keys it names. Images and icons replace the owner’s file whole. - A
.tsxshadow exports the same name as the file it shadows, with the same Props type (ADR 0305 rule 12). - A declaration shadow extends its base class under the
Base<Name>alias (ADR 0305 rule 1), and may change only what its kind allows. A placement shadow of a widget is the example: it carries the placement fields, not the query.
Base<Name> alias (rules 2 and 6). A behaviour swap is a driver (rule 9), and a configuration override is a subclass in src/config/ (rule 10).
Five layers. A placement, for example a widget’s slot and order, is set in one of five layers. For a
given item, a higher layer’s placements replace the whole set of the lower layer’s, and never merge with them.
- Layers 1 to 3 are code, and gen checks them. Layers 4 and 5 are data, validated when they are saved and again when they are read (ADR 0307). A key that no longer exists is dropped on read, and a size the display does not allow is clamped.
- A placement never changes a query or a display. Those belong to the owner.
- A behaviour swap stays a driver that replaces a port (
@Replaces(Port)). It is not an override in the tree. - Configuration stays in
src/config/. Configuring a package is not overriding it. A config override is a subclass insrc/config/of the package’s config class, under theBase<Name>alias (ADR 0305 rule 1).
- Gen fails with
override_target_missingwhen a shadow’s owner file does not exist,override_shape_mismatchwhen a shadow does not match its owner’s exports or Props, andoverride_duplicatewhen two shadows name the same target in one member. - When a package upgrade moves or removes a shadowed file, gen lists every shadow whose target changed, with the
code
override_target_changed. It is a warning that the review reads. It does not fail the build.
Consequences
- A reviewer checks one folder on each upgrade. The shadows and their targets are visible in the tree.
- A shadow is typed and checked against its owner, so a renamed export fails at gen and not at run time.
- The placement layers have a fixed order, so the question “why does this tile sit here” has one answer.
- Hosts that wrote
assets/overrides/or.override.tsxfiles move them into the tree. The template does this in the conversion pass (STA-344). - Gen must read the tree and report on it, which is planned work (STA-339).
Enforcement
- planned — STA-339: the overrides tree resolver and its gen errors (
override_target_missing,override_shape_mismatch,override_duplicate, and the warningoverride_target_changed). - planned — STA-340: the Props and export match for a
.tsxshadow, and theBase<Name>alias check of ADR 0305 rule 1. - The layer order (rule 7) is enforced by gen once the widget placement checks of ADR 0307 land.