Preset packs¶
plc-st-review ships no opinionated naming or style defaults: the
out-of-the-box config has every per-team rule disabled. Different shops
disagree on conventions (some prefix bools with x, some suffix enum
types with _enum, some use both, some neither), and the engine has
no business taking a side.
The extends: mechanism lets your team compose its own policy and
share it across projects, the same way ESLint and Prettier do.
How extends works¶
.plc-st-review.yml is the project's config file. Anywhere it accepts
a value, it also accepts an extends: pointing at one or more "preset"
files that contribute the same shape:
# .plc-st-review.yml at the project root
extends:
- ./presets/company-standards.yml # baseline applied to every project
- ./presets/injection-molding.yml # vertical-specific overrides
# Local overrides applied last (highest precedence)
disabled_checks:
- COMMENT_ONLY
naming_conventions:
fb_instance: { prefix: fbInj }
Rules of resolution:
extends:accepts a single path or an array. The list is walked in order; entries later in the list override earlier ones.- Paths can be relative to the file that declares
extends:, or absolute. - A preset can itself extend another preset,
extends:chains as deep as you want. - The local config (the file you're loading) always overrides any values its presets set.
- Cycles (
a → b → a) are detected and reported as an error. - Resolution is filesystem-only in v0.x. No npm packages, no HTTP URLs, no git refs. If you want to share presets across repos, vendor them via a git submodule or copy them in.
Merge semantics by field¶
| Field | How it merges |
|---|---|
extends |
Replaced (not relevant in the merged result) |
disabled_checks |
Union, every preset's entry is collected |
severity_overrides |
Map merge, later wins |
ignore_paths |
Union |
safety_critical_prefixes |
Override (last writer wins) |
forbidden_symbols |
Union |
naming_conventions |
Map merge, later wins on each dimension |
naming_ignore |
Union |
reporting.* |
Map merge |
A worked example¶
Imagine your shop builds two product lines: injection-molding machines and CNC mills. You want a common baseline and a vertical-specific overlay.
# presets/company-standards.yml, reused across all projects
# Every team agrees on these.
safety_critical_prefixes:
- SAFETY_
- INTERLOCK_
severity_overrides:
CONSTANT_VALUE_CHANGED: warn
# Naming policy applied to every project. Per-vertical packs can extend
# or override individual dimensions.
naming_conventions:
bool: { prefix: x }
int: { prefix: i }
real: { prefix: r }
string: { prefix: s }
pointer: { prefix: p }
enum_type: { suffix: _enum }
structure_type: { suffix: _type }
fb_instance: { prefix: fb }
global_var: { prefix: g }
function_block: { prefix: FB_ }
function: { prefix: fn }
# presets/injection-molding.yml, only the bits that change
# Injection cycle timing is safety-relevant on these machines.
severity_overrides:
TIMER_VALUE_CHANGED: error
# Naming: machine FB instances get the `fbInj` prefix.
naming_conventions:
fb_instance: { prefix: fbInj }
# We've never used SR latches in this product line; ban them.
forbidden_symbols:
- /\\bSR\\b/
# Suppress this, too noisy on the legacy code we inherited.
disabled_checks:
- BISTABLE_DOMINANCE_MISMATCH
# presets/cnc.yml, different vertical, different baseline
severity_overrides:
LOOP_BOUNDS_CHANGED: warn # spindle programs run lots of FOR loops
TIMER_VALUE_CHANGED: warn # not as safety-critical as molding
naming_conventions:
fb_instance: { prefix: fbCnc }
# .plc-st-review.yml in a specific repo
# Pick one of the verticals.
extends:
- ./presets/company-standards.yml
- ./presets/injection-molding.yml
A different repo, different extends:
# .plc-st-review.yml in a CNC-mill repo
extends:
- ./presets/company-standards.yml
- ./presets/cnc.yml
Sharing presets across repos¶
Three patterns, in increasing complexity:
- Copy: every project keeps a
presets/directory; you update them when the standard changes. Lowest friction, highest drift. - Git submodule: keep
presets/as a submodule of a sharedstandardsrepo. One source of truth; updates are explicit per project. - CI-injected: your CI clones the
standardsrepo before runningplc-st-reviewand pointsextends:at the checkout. Same single-source-of-truth without per-project submodule plumbing.
There is no "right" answer; pick the one that matches how your team already handles shared standards.
What the engine does NOT ship¶
- No vendor-flavored presets (no Beckhoff / CODESYS / TwinCAT / ABB / Siemens preset). The engine stays portable; conventions live in your repo.
- No "recommended" preset. Every check ships with a default severity, but no preset tells you what to ban or rename. Your team decides.
- No preset versioning or registry. Presets are plain YAML files in your control; their lifecycle is part of your project, not the tool.
Validating a preset¶
To check that a preset file loads cleanly, point the CLI at it (with no diff target) and let the config loader validate the syntax:
If the file has invalid YAML, an unknown naming dimension, or a malformed regex, the CLI exits with a clear error.