Skip to content

Configuration

Qualimetrix works out of the box with sensible defaults. A configuration file lets you customize thresholds, disable rules, and exclude paths to fit your project.


Configuration File

Automatic discovery accepts exactly qmx.yaml or qmx.yml in the working directory and, when neither exists, qmx.dist.yaml or qmx.dist.yml. If both names of a pair exist, the command refuses with exit code 3 — both dist names are refused even beside a local file, since a checkout without it would refuse them; choose one with --config. A near spelling, such as QMX.yaml or qmx.yaml.dist, is warned about and not loaded when no local name exists. A local file beside a near name is loaded without that warning; a dist file loaded in its absence keeps it, since such a name is usually a misnamed local file. --config selects its named file explicitly, independently of automatic discovery.

Committed defaults and a local file. Commit qmx.dist.yaml and ignore qmx.yaml in Git: a checkout without qmx.yaml, such as CI or the GitHub Action, reads qmx.dist.yaml. A developer's qmx.yaml wins and is read alone — it builds on the committed file only by importing it:

# qmx.yaml (not committed)
imports:
  - qmx.dist.yaml

fail_on: warning

When an auto-discovered qmx.yaml or qmx.yml does not import a qmx.dist.yaml or qmx.dist.yml beside it, the run warns that the dist file is not used, since the local run then differs from CI. When a run without the local file would refuse the dist file — it is not a readable regular file, is not valid YAML, or names an import that cannot be read — the warning gives that refusal instead. The advice names the dist file by its full path when the local file is a symlink into another directory, whose imports resolve beside its target. A dist file selected with --preset is read in the preset band only: it is neither discovered nor warned about.

A near-name warning is suppressed only when that same physical file was already selected as a custom preset; the same basename elsewhere does not suppress it. The two-file refusal identifies both files. If the working directory cannot be listed, discovery refuses with exit 3 and names the directory.

Every command that reads the document judges all its context-free values, even when it consumes only some sections. The command's CLI profile does not hide malformed authored configuration.

Commands Document and paths Shared CLI settings
check, directives Read the document and analyse resolved paths Their analysis options
debug:layer-assignment Read the document and analyse configured paths --config, --preset and its analysis settings
graph:export Read the document; use resolved paths when none are given --config, --preset, --exclude, --include-generated, --include-autoload-dev, --no-cache, --workers, --memory-limit
rules Read the document without requesting analysis paths; include named computed metrics and mark the current only_rules/disabled_rules selection --config, --preset
baseline:generate, baseline:update, baseline:cleanup, baseline:explain Read the document and measure resolved paths --config, --preset, rule selection, --include-generated, --include-autoload-dev, --no-cache, --workers, --memory-limit
baseline:rename-channels, hook:install, hook:status, hook:uninstall, help, list, completion Do not read the configuration document Their own command options

Graph's --format/-f selects dot or json separately from the document's analysis format. Graph consumes Run, Cache, Parallel, Coupling and memory settings, without constructing Finding selection or the analysis output format.

You can also specify a file explicitly:

vendor/bin/qmx check src/ --config=my-config.yaml

The file found or named this way is the root configuration file. It can build on other files and built-in presets through imports.


Configuration Sections

Paths

Directories or PHP files to analyze:

paths:
  - src/

Note

If you pass paths as CLI arguments (e.g., vendor/bin/qmx check src/ lib/), they take precedence over the config file.

Without authored paths in CLI, YAML or presets, defaults come from the analysed project's invocation snapshot of composer.json. If its selected autoload records are unusable, inferred defaults refuse with exit 3 rather than analysing unrelated paths. Accepted fragments of a damaged manifest can still be analysed, but inferred partial defaults do not establish a whole project. Explicitly selecting the whole root can establish filesystem completeness with state unknown; final removal/uncertainty can still withhold declaration claims. Selecting a subset without a complete declared universe gives unmeasured. See Project scope. A missing path or an explicitly named existing non-PHP regular file refuses with exit 3 in every measuring command before discovery.

Input directories must canonically target the captured root or a descendant; an external alias spelling targeting an internal directory is valid. For files, the canonical parent is checked and the last name is kept literally, including file symlinks. . and equivalent root spellings are valid. A directory targeting outside refuses with exit 3; --working-dir chooses the intended root.

Exclude

Filesystem entries removed from analysis: files, directories and other matching entries. The walk does not descend into an excluded directory:

exclude:
  - subtree: tests/Fixtures

Each entry is an explicit exact, subtree or regex selector, as under suppress_paths; a bare string is refused. The built-in vendor, node_modules and .git floor is separate from authored selectors. Authored exclusions apply to named CLI, YAML and preset paths without refusing a root merely because it was written explicitly. All matching selectors bind before an entry is pruned. A complete run with analyzed=0, failed=0 and excluded + generatedExcluded > 0 is intentionally empty and succeeds with its measured scope explanation. baseline:generate writes an empty file; any failure takes priority with exit 4. See Paths argument.

Include Generated

By default, files with a @generated annotation in the first 2 KB are automatically skipped from analysis. To include them:

include_generated: true

Equivalent CLI: --include-generated

Include Autoload Dev

By default, the code composer.json declares under autoload-dev is not part of the project: a run with no paths analyses only the paths autoload declares (in any autoload form: psr-4, psr-0, classmap, files), and a run is judged against those alone when Qualimetrix asks whether it covered the whole project. To count test code as part of the project in both places:

include_autoload_dev: true

Paths you write yourself are not widened; with paths: [src], the run is reported as not covering the autoload-dev paths. In either section, an entry that is, or lies inside, a vendor, node_modules or .git directory is not part of the project: it is neither analysed by default nor counted, and a warning names it.

Equivalent CLI: --include-autoload-dev

Suppress Paths

Path selectors suppress violations while the files are still analyzed. Each YAML item is a one-entry mapping: exact selects one canonical project-relative path, subtree also selects /-separated descendants, and regex accepts a delimiterless PCRE fragment that Qualimetrix anchors to the whole path:

suppress_paths:
  - subtree: src/Entity
  - exact: src/DTO/Address.php
  - regex: 'src/Metrics/.*Visitor\.php'

Also available as a CLI option: --suppress-path (merged with YAML config).

Namespace and project findings have no borrowed source file, so path selectors do not suppress them. Migrate intended namespace suppression to suppress_namespaces or a specific suppress_namespace_channels entry.

Declared project scope remains exempt

suppress_paths does not suppress architecture.circular-dependency cycles or declared project-scoped diagnostics. Exemption is declared per channel; the architecture. prefix alone grants none.

architecture.layer-violation belongs to the source declaration: global suppress_paths matches the physical dependency site's file, while suppress_namespaces matches the source namespace. Excluding only the target does not suppress an outgoing violation. Git reports retain it only when the source file changed, in both modes; see Git Integration.

Inline directives and baselines still apply to layer violations, but not to the five configuration validators. Their separate controls are described under Architecture rules. Per-rule exclusions remain available independently of global channel scope.

Suppress Namespaces

Suppress violations for classes in selected namespaces. Namespace selectors use the same three explicit forms; subtree follows \ namespace boundaries and regex is automatically full-subject:

suppress_namespaces:
  - subtree: App\Tests
  - exact: App\Generated\BuildInfo
  - regex: 'App\\Legacy(?:\\[^\\]+)*'

This is useful when entire namespace subtrees should never produce violations. For per-rule exclusions, use suppress_namespaces inside a rule configuration instead (see below).

Also available as a CLI option: --suppress-namespace (merged with YAML config).

Declared project scope remains exempt

suppress_namespaces does not suppress architecture.circular-dependency cycles or declared project-scoped diagnostics. Exemption is declared per channel; the architecture. prefix alone grants none. The per-rule form of the option is refused for such producers; see the note under Works for every rule.

architecture.layer-violation belongs to the source declaration: global suppress_paths matches the physical dependency site's file, while suppress_namespaces matches the source namespace. Excluding only the target does not suppress an outgoing violation. Git reports retain it only when the source file changed, in both modes; see Git Integration.

Inline directives and baselines still apply to layer violations, but not to the five configuration validators. Their separate controls are described under Architecture rules. Per-rule exclusions remain available independently of global channel scope.

Rules

Control which rules are active and set custom thresholds.

Disable a rule entirely:

rules:
  code-smell.boolean-argument:
    enabled: false

Override thresholds:

Each rule defines severity levels. When a metric reaches or crosses a threshold in the rule's adverse direction, a violation is reported at that severity. For example, the cyclomatic complexity rule has thresholds for methods:

rules:
  complexity.ccn:
    callable:
      warning: 15
      error: 25

This means: report a warning when a method's cyclomatic complexity reaches 15, and an error when it reaches 25.

Threshold shorthand:

If you want a single pass/fail threshold (all violations become errors), use the threshold key:

rules:
  complexity.ccn:
    callable:
      threshold: 15    # warning=15, error=15 → all violations are errors

  size.method-count:
    threshold: 25      # same as warning: 25, error: 25

This is useful in CI where you want a simple pass/fail cutoff without graduated warnings. You cannot mix threshold with explicit warning/error keys from the same configuration layer (the same preset, the same qmx.yaml, or the same CLI invocation) for the same rule level — that raises a configuration error.

Overriding the mode across layers: a higher-priority layer (config file over a preset, CLI over the config file) may freely switch mode for a rule level — e.g. a strict preset sets warning/error, and --rule-opt=size.method-count:threshold=25 on the command line switches that rule to a single cutoff. The CLI's threshold overrides the preset's warning/error instead of conflicting with them:

# qmx.yaml (or a preset)
rules:
  size.method-count:
    warning: 10
    error: 20
# CLI switches this rule to simple pass/fail mode — no "cannot mix" error
bin/qmx check src/ --rule-opt=size.method-count:threshold=25

The same applies in the other direction (a lower layer's threshold overridden by a higher layer's warning/error), and to hierarchical rules at the level the keys are set (e.g. complexity.ccn's callable:/class:). Duplication is an exception: duplication.clone accepts positive min_lines, min_tokens, and error only; warning and threshold are refused, and severity uses each copy's covered code lines. Its option schema is listed in the rule table below.

Hierarchical shorthand is a per-layer form. A top threshold changes the callable band of CCN/cognitive/NPath and preserves the class band's values and defaults. Write class.enabled:false if class reporting should be off. A top shorthand and an explicit write to the same expanded leaf in one layer refuse; an independent child in a target level block can coexist. To configure both levels in one layer:

rules:
  complexity.ccn:
    callable:
      threshold: 5
    class:
      max_warning: 2
      max_error: 3

CBO and instability spread a top band to class and namespace in the writing layer. An explicit write conflicts only at an overlapping expanded leaf in that layer; independent level children coexist. A higher layer may override the expanded leaves of a lower layer without discarding unrelated values.

Each type-coverage dimension is a rule of its own, so each takes its own bare threshold:

rules:
  design.type-coverage.param:
    threshold: 90
  design.type-coverage.return:
    threshold: 90
  design.type-coverage.property:
    threshold: 80

Option key spellings are interchangeable, option keys themselves are not. max_warning, maxWarning and max-warning are the same key and all three apply, at both depths. Being one key, it is written once: two spellings of it in the same block — max_warning: 1 beside maxWarning: 999 — end the run with exit code 3 instead of letting the later one win. The same holds for every key in the document, root keys included. A key the rule does not have at that position is not guessed at: the run stops (see Unknown rule option keys).

An empty level block writes no values. callable: {} preserves the lower layer and uses defaults only for leaves no layer wrote. To switch a level off, write callable: {enabled: false} — callable: false is refused, because a level has no off-switch of its own and the value looks like the rule's.

Suppress namespaces for a rule:

Any rule can use the same explicit namespace selectors:

rules:
  complexity.ccn:
    suppress_namespaces:
      - subtree: App\Tests
      - subtree: App\Legacy
    callable:
      warning: 15
      error: 25

  coupling.cbo:
    suppress_namespaces:
      - subtree: App\Tests
    suppress_paths:
      - subtree: src/Infrastructure/DependencyInjection

This is useful when certain namespaces (e.g., tests, generated code, legacy modules) should not trigger violations for a specific rule, while still being analyzed for metrics.

Suppress selected namespace-aggregate channels for a rule:

Use suppress_namespace_channels when one violation channel is structurally inapplicable to part of the namespace tree, but class findings and the producer's other channels must remain:

rules:
  health.cohesion:
    suppress_namespace_channels:
      health.cohesion:
        - subtree: App\Metrics\Coupling
        - regex: 'App\\Generated(?:\\[^\\]+)*'

The option is a non-empty map from channel selector to a non-empty list of explicit namespace selectors. The key uses the closed channel grammar — an exact channel name, or X.* for the strict descendants of X, either optionally narrowed to a level with :namespace; see Rule and channel selectors below. A bare prefix such as health is an error, not a group: write health.*. Exact health.cohesion leaves the sibling health.coupling untouched.

Write the channel exactly as it is named, hyphens included — these keys are not case-normalized, so size.class-count, code-smell.* and a computed metric named computed.my-score are written here the way they are written everywhere else.

The key must address a channel the rule it is written under actually emits. A key that names another rule's channel, or no channel at all, ends the run with exit code 3 and a message listing that rule's channels — it used to be accepted and exclude nothing. A key carrying a level is judged as one thing: the channel it names must be produced by this rule and report at that level, so coupling.*:namespace under coupling.class-rank is refused even though a sibling coupling channel does report at namespace level.

namespace is the only level such a key can name, because the option is offered namespace-aggregate findings and nothing else. coupling.cbo:class is refused by name — it used to be accepted and could never fire:

rules:
  coupling.cbo:
    suppress_namespace_channels:
      # the namespace aggregate only; the class findings of the same channel stay reported
      coupling.cbo:namespace:
        - subtree: App\Legacy

Writing the level is optional: a level-free key already reaches only namespace aggregates, so coupling.cbo and coupling.cbo:namespace exclude the same findings. The pair is worth writing when the key should say out loud which half of a two-level channel it is about.

Only namespace-aggregate findings are removed

The option filters findings whose subject is a namespace. A rule that reports per occurrence (code-smell.*, security.*, architecture.layer-violation) or only per class (cohesion.lcom) has nothing for it to remove, and a key naming such a channel is accepted and then does nothing. The five layer-policy diagnostics — architecture.coverage-gap, architecture.unreachable-layer, architecture.potential-shadow, architecture.empty-template, architecture.pending-layer-matched — report against the project as a whole and are likewise outside its reach; use the exclude: block inside the architecture layer configuration instead.

Only aggregate Namespace violations are removed. Class-level health.cohesion findings in the same namespace and sibling channels remain. The existing suppress_namespaces option is unchanged and stays producer-wide across class and namespace findings.

Works for every rule, including the architecture rules

suppress_namespaces, suppress_namespace_channels, and suppress_paths are extracted and applied at the framework level for rule names regardless of whether that rule's Options class declares such a field — this is deliberately not opt-in per rule. That includes architecture.layer-violation. Global exclusions apply to source-owned layer violations. The per-rule form explicitly names the producer whose findings should be suppressed. See the architecture rule's Suppression section for the reasoning.

Producers with project-scoped findings only

A non-empty per-rule suppress_namespaces or suppress_paths is refused at load (exit 3) for a producer whose every channel is project-scoped: its findings are about the project, so no path or namespace can address them. The producers are architecture.circular-dependency, architecture.layer-declaration, architecture.unassigned-class, baseline.unused-entry, coupling.unmatched-framework-namespace, discovery.unmatched-exclude and suppression.configuration. An empty list or null is accepted. The same refusal applies when the option is written with --rule-opt. Producers with at least one file-scoped channel (for example cohesion.lcom) and computed metrics are not affected, even when a computed metric is configured to report only at the project level.

The refusal happens in every command that resolves rule options: check, directives, debug:layer-assignment, rules and baseline:generate, baseline:update, baseline:cleanup, baseline:explain. graph:export does not interpret rule options, so it does not refuse them. To accept known findings of such a producer, see the baseline page for which findings a baseline can accept; for dependency cycles, narrow what counts as an edge with ignore-relations of architecture.circular-dependency.

Suppress paths for a rule:

Any rule can use the same explicit path selectors. Violations from matching files are suppressed:

rules:
  coupling.cbo:
    suppress_paths:
      - subtree: src/Metrics
      - regex: 'src/Metrics/.*Visitor\.php'

This works alongside suppress_namespaces -- both filters are applied. Unlike the global suppress_paths, per-rule suppress_paths only affects the specific rule, not all rules.

Visibility: unlike @qmx-ignore, these suppressions happen silently by default — nothing in the default output hints that violations were dropped. Run with -v to see a per-rule breakdown of how many violations were suppressed this way (the namespace bucket combines suppress_namespaces and suppress_namespace_channels, separately from suppress_paths), and add --show-suppressed to also list each suppressed violation, alongside @qmx-ignore suppressions.

Per-symbol threshold overrides with @qmx-threshold:

In addition to project-wide thresholds in YAML, you can override thresholds for individual classes or methods using @qmx-threshold annotations directly in source code:

/**
 * @qmx-threshold complexity.ccn warning=20 error=40
 */
class ComplexStateMachine
{
    // Methods in this class use higher complexity thresholds
}

The class-level override also applies to method evaluations inside the class; a narrower callable-level override takes precedence.

See Baseline > @qmx-threshold for full syntax and examples.

Rule and Channel Selectors

Every place that names a rule or a finding channel — disabled_rules, only_rules, their CLI equivalents, suppress_namespace_channels, and the @qmx-ignore family in source code — reads the name the same way:

Form Meaning
complexity.ccn exactly that name, and nothing else
complexity.* strictly the descendants of complexity — complexity.ccn, complexity.wmc and so on. complexity itself is not included; if a name is both a rule and a channel, address it separately
coupling.cbo:namespace the channel narrowed to one level of the aggregation tree. The level is one of callable, class, file, namespace, project, and the channel must report at it

A bare prefix is not a group. complexity on its own selects nothing and is rejected:

Configuration error: Rule selector "complexity" does not match any registered producer or channel. Write "complexity.*" to select its descendants.
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

A X.* that has no descendants is rejected for the same reason. Most rules emit a single channel whose name equals the rule name, so code-smell.eval.* is an error — write code-smell.eval.

An unresolvable selector in configuration or on the command line ends the run with exit code 3 before any report is produced. Guessing at intent was the previous behaviour, and it silently turned typos into "nothing was selected".

Which side of the pair a name refers to is decided by the directive, not by the name. The same string means different things depending on where it is written:

  • @qmx-ignore code-smell.boolean-argument always names a channel, because a suppression belongs to the channel;
  • @qmx-threshold code-smell.boolean-argument always names a rule, because a threshold belongs to the rule's one options object. @qmx-threshold therefore takes an exact rule name and accepts no wildcard at all — resetting a threshold across a group was a footgun, not a feature;
  • keys of the rules: section and the owner before : in --rule-opt RULE:option=value name a rule, exactly. A key like rules: { complexity: {...} } used to be accepted and configure nothing at all; it is now rejected.

See Baseline for the full inline-directive syntax, and Rules > Annotations for what the tool reports when a directive addresses nothing.

Disabled Rules

Disable specific rules, channels, or whole groups:

disabled_rules:
  - code-smell.boolean-argument
  - duplication.clone

Equivalent CLI: --disable-rule=code-smell.boolean-argument --disable-rule=duplication.clone

To disable a whole group, use the wildcard:

disabled_rules:
  - code-smell.*

Only Rules

Filter directly selected rules; declared diagnostic roles may also be admitted:

only_rules:
  - complexity.ccn
  - complexity.cognitive

Equivalent CLI: --only-rule=complexity.ccn --only-rule=complexity.cognitive

Fail On

Control which severity levels cause a non-zero exit code:

fail_on: error    # Only fail on errors (default)
# fail_on: warning  # Fail on warnings too
# fail_on: none     # Never fail on violations

The default is error: warnings and Info-level diagnostics are shown in the output but do not cause a non-zero exit code. Use fail_on: warning if you want warnings to also fail the build.

Use fail_on: none to keep findings from failing the run. The former YAML fail_on: false is refused; replace it with none.

info is report-only and is not a fail_on value

warning and error are the only severities fail_on accepts — fail_on: info is rejected with an error naming the accepted values. Severity info means "observe, do not gate": an Info-only run always exits 0, whatever fail_on says. To gate on a diagnostic configured at info, raise that rule's own severity instead. annotation.unused-directive defaults to warning; explicitly set info to preserve the former quiet cleanup severity:

rules:
  annotation.directive:
    unused-directive-severity: info

fail_on does not govern configuration errors

Some channels report a mistake in the configuration rather than debt in the code — the five layer-policy diagnostics (architecture.coverage-gap, architecture.unreachable-layer, architecture.pending-layer-matched, architecture.potential-shadow, architecture.empty-template) and the three inline-directive diagnostics (annotation.unresolved-directive, annotation.unsupported-threshold, annotation.invalid-threshold). These never take part in the fail_on comparison at all: they end the run with a non-zero exit code even under fail_on: none, and no baseline entry or @qmx-ignore can accept them. The tool is not judging your code there — it is saying it cannot do what you asked.

Exclude Health

Exclude specific health dimensions from scoring. The excluded dimensions are not shown in the health summary and do not contribute to the overall score:

exclude_health:
  - typing
  - maintainability

Equivalent CLI: --exclude-health=typing --exclude-health=maintainability

Memory limit

Set the PHP memory limit for analysis. By default, PHP's memory_limit from php.ini is used. The limit applies to the worker processes as well, where files are parsed and measured; a file a worker could not finish within it is reported as failed, and the failure names the limit.

memory_limit: 1G    # 1 gigabyte
# memory_limit: -1  # Unlimited

Equivalent CLI: --memory-limit=1G. A value above PHP_INT_MAX bytes refuses with exit 3.

Format

Set the default output format:

format: summary   # Default
# format: json
# format: html

Cache

Control AST caching for faster repeated runs:

cache:
  enabled: true         # Default: true
  dir: /home/user/.cache/qmx  # Optional explicit POSIX path outside this project

dir is parsed as a string. When caching is enabled or --clear-cache uses the location, an absolute path or a path relative to the project root must resolve to a supported POSIX path outside the project; for example, ../external-cache can qualify. A quoted numeric name is a string, then receives the same runtime path judgement if the location is used. --no-cache without clearing does not judge an unused root. The default is the user cache directory under qmx, shared across projects; old .qmx-cache entries are not read. An explicit root owned by another user or writable by group/others refuses when used; an unusable default disables caching with one warning. Root eligibility does not establish trust for every ancestor. The cache uses a current-format allowlisted AST codec; old formats are misses. When the project root is / (for example, a cron invocation from /), containment is not checked; all other location judgements still apply. short_open_tag participates in the key. Entries unread for 30 days are swept incrementally. Each open sweeps 16 of 256 shards; after 16 successful sweep steps, the per-format target is 2 GiB plus entries written since each shard's last sweep and one oversized newest entry per shard, rather than an immediate hard quota. Publication temporary files are retained for up to the same 30-day age limit so a sweep does not remove an active writer; their bytes are additional to this entry target. Old temporary files are swept in both shards and version metadata. Clearing preserves unrelated files and refuses while any detached cache directory remains.

Equivalent CLI: --no-cache to disable, --cache-dir=DIR to change directory.

Parallel Processing

Control the number of parallel workers for file analysis:

parallel:
  workers: 4     # Fixed number of workers
  # workers: 0   # Disable parallelism (sequential)
  # workers: 1   # Disable parallelism (single-process)

By default, Qualimetrix auto-detects the worker count based on CPU cores. Equivalent CLI: --workers=4. On an eligible run, an explicit count above one uses processes and refuses with environment exit 3 if the first worker cannot start or answer within 10 seconds; automatic selection warns and falls back to sequential. ext-parallel threads and forks are not transports.

Tip

Use workers: 1 for debugging or single-process environments. workers: 0 disables parallelism (sequential execution); auto-detect is the default when the option is omitted.

Namespace Detection

Qualimetrix derives project namespaces from the invocation working directory's composer.json and falls back to source parsing where needed. Namespace detection is not configurable: namespace.strategy and namespace.composer_json are rejected as unknown keys.

Coupling

Configure framework namespace prefixes for the CBO (Coupling Between Objects) metric. Dependencies on framework namespaces are tracked separately as coupling.cbo-app and coupling.ce-framework:

coupling:
  framework-namespaces:
    - subtree: Symfony
    - subtree: Doctrine
    - subtree: Psr
    - subtree: Illuminate

When no framework-namespaces are configured, coupling.cbo-app equals coupling.cbo (no effect).

Aggregation

Namespace aggregation follows the analyzed declarations. Custom aggregation.prefixes and aggregation.auto_depth settings are no longer supported and are rejected as unknown keys.

Architecture

Layer rules and the allow-list for the architecture.layer-violation rule live under the top-level architecture: key. The full schema is documented in Architecture Rules; the keys most relevant to general configuration are:

architecture:
  layers:
    - name: 'domain-{module}'                         # template layer with capture variable
      patterns: ['App\Module\{module}\Domain\**']
    - name: shared-kernel
      patterns: ['App\Shared\**']

  allow:
    'domain-{m}':
      - shared-kernel
      - target: 'domain-{m}'
        relations: [implements, extends]              # whitelist of dependency kinds

  coverage-gap: ignore                                # ignore | warn | error
  max_expanded_layers: 500                            # cumulative cap on template expansion

Capture variables in layer names and patterns use the syntax {name} (single namespace segment) or {name:**} (cross-segment). The same variable name within one layer entry binds to one value (co-binding); variables in different entries are independent. See the layer-templates section for the full grammar.

A layer and its exclude: accept six criterion lists: patterns, attributes, member_attributes, implements, extends, and suffix. attributes observes attributes on the class-like declaration; member_attributes observes its own members. match: any is the default; all requires each populated criterion kind. Layer capture patterns and public exact | subtree | regex selectors are distinct grammars. Membership suggests a pattern equivalent when refusing a public selector form; YAML/CLI public selectors require explicit kind syntax and do not translate a bare Architecture pattern. A template with match: any refuses a captureless pattern, while match: all can use one beside a capturing pattern.

architecture.layer-declaration independently owns declaration diagnostics and has only enabled. Its five configuration-error channels remain live under an unrelated --only-rule; its four ordinary channels follow channel publication. Disabling architecture.layer-violation does not disable declaration diagnostics. See the selection table.

An enabled architecture.unassigned-class with mode: warn or error requires a non-empty final architecture.layers, even when the file explicitly writes layers: []. Ignored, disabled or unselected unassigned-class does not impose that requirement. The refusal names the configuration that wrote the mode.

max_expanded_layers caps the total number of concrete layers produced by template expansion across all templates (default 500). The cap protects against pathological broad templates whose binding tuples would blow up the layer count. Raise the ceiling explicitly when a monorepo legitimately has more bounded contexts than the default allows; overflow rejects at expansion with an actionable error.

Computed Metrics

The computed_metrics: root key configures the six built-in health scores (health.complexity, health.cohesion, health.coupling, health.typing, health.maintainability, health.overall) and any user-defined computed metrics. This is a large enough surface — accepted keys, thresholds, custom formulas, available variables and functions — to have its own reference: see Health Scores > Configuration for the full schema.


Presets

Presets are named configuration bundles that apply predefined settings — thresholds, disabled rules, fail behavior — in a single flag. Instead of manually tuning dozens of options, pick a preset that matches your project's maturity.

Preset Description
strict Tight thresholds for greenfield projects. Sets fail_on: warning
legacy Relaxed thresholds for legacy codebases. Disables noisy rules
ci Explicit CI mode. Sets fail_on: error
# Use a single preset
vendor/bin/qmx check src/ --preset=strict

# Combine multiple presets
vendor/bin/qmx check src/ --preset=strict,ci

# Use a custom preset file
vendor/bin/qmx check src/ --preset=./my-preset.yaml

Priority order: Presets are applied after composer.json discovery but before qmx.yaml, left to right. Your config file sits above every preset, and the command line above the file.

Multiple presets: Presets combine with each other exactly as a preset combines with your file — each key by its own policy, described in How layers combine. For example, --preset=legacy,ci gives you legacy thresholds with CI fail behavior, because fail_on is a scalar the later layer wins.

Warning

only_rules is not accumulated across layers — the last layer that writes it replaces the list whole. This is intentional: only_rules is a restrictive filter, and union would widen the scope. disabled_rules accumulates authored statements, but a later exact producer enable can reverse an earlier disable; see Rule selection.

Custom presets: Any YAML file with the same structure as qmx.yaml can be used as a preset. Pass the file path instead of a built-in name.

Presets from the configuration file: a built-in preset can also be imported by name — imports: [strict] in qmx.yaml — so every tool that reads the file, including the pre-commit hook and the GitHub Action (neither passes --preset), judges by it. See Built-in presets. A file given to --preset cannot itself import.


Splitting a configuration

The root configuration file can list the files it builds on under imports:

# qmx.yaml
imports:
  - strict                    # a built-in preset, by name
  - config/architecture.yaml  # one file
  - subtree: config/teams     # every .yaml / .yml file below the directory

fail_on: error

An entry is one of three things:

  1. A built-in preset — a string with no /, no \ and no extension: strict, legacy or ci.
  2. A file path — any other string, ending in .yaml or .yml (in any letter case). *, ? and [ are ordinary characters in it.
  3. A selector — a one-entry mapping, {subtree: …} or {regex: …}, that stands for a set of files; see Selectors.

Each imported file is a layer of its own, written like any configuration file. The layers are the entries in the order written, then the root file: for the list above, strict, config/architecture.yaml, the files below config/teams, qmx.yaml. A later entry overrides an earlier one, and the root file overrides them all — each key by the policy described in How layers combine. The whole chain sits where qmx.yaml sits: above every preset given on the command line, below the command line itself. -v names every file in that order (Configuration loaded from: defaults, strict, config/architecture.yaml, config/teams/a.yaml, config/teams/b.yaml, qmx.yaml, cli).

Paths. An imports entry is resolved against the directory of the file that writes it, so --config=sub/qmx.yaml with imports: [base.yaml] reads sub/base.yaml, and an imported config/a.yaml with imports: [b.yaml] reads config/b.yaml. When a file is a symlink, that is the directory of the file it points to: a configuration linked into a project reads the bases beside it. Every other path, in any file of the chain — paths, exclude, cache.dir — keeps the working directory as its base, exactly as in the root file. Refusals and -v name an imported file by that path as seen from the file that imported it (./ dropped, .. kept) — or by its full path when that file is a symlink — together with the file that imported it.

Built-in presets

imports: [strict] applies the built-in preset the way --preset=strict does, but from the configuration file. This is what makes the pre-commit hook and the GitHub Action — neither passes --preset — judge by the same rules as a local qmx check --preset=strict.

  • The preset sits where the file naming it sits in the chain, so the file's own keys override it. A preset given with --preset stays below the whole chain.
  • Name it by its bare name. A bare name that is not built-in is refused at its position: Unknown preset "x". Available presets: ci, legacy, strict. A file needs a .yaml or .yml extension. To import a file of your own, write its extension (team.yaml).
  • Refusals and -v call it strict, and source[] in JSON reports it as {"kind": "preset", "name": "strict", "imported_by": {…}}. The same preset given with --preset is a separate layer named preset:strict; naming it both ways applies it in both places.
  • Only built-in presets are imported by name. A preset file of your own is a file: import it by path.

Selectors

A selector stands for a set of files that changes without anyone editing the root file, such as config/qmx that other tools drop their parts into. It has the same shape as the selectors of suppress_paths:

imports:
  - subtree: config/qmx                                   # the directory and everything below it
  - regex: 'vendor/acme/[^/]+/qmx-extension\.yaml'         # the whole relative path matches
  • Which files. Every file whose name ends in .yaml or .yml (in any letter case) below the directory of the file that writes the entry, named by its path from that directory. A selector never reaches above that directory; a file above it is a plain string entry (../shared.yaml).
  • subtree names a directory below the importing file's directory and stands for every file below it, at any depth. The directory must exist. {exact: …} is refused: a single file is a plain string.
  • regex is a PCRE fragment that must match the whole path from the importing file's directory (config/teams/a.yaml, not a.yaml), the same way as in suppress_paths. The literal directory it starts with bounds the walk: vendor/[^/]+/qmx\.yaml looks only inside vendor/, and that directory must exist and is matched by the names on disk, letter for letter. A fragment that starts with a metacharacter, or holds | or ) anywhere, walks the importing file's whole directory — vendor/ and node_modules/ included — and is refused by any directory below it that cannot be listed or entered, even one the pattern could never match. Start the regex with a literal directory (config/qmx/…) to limit the walk and avoid that.
  • Order. The files one selector stands for have no order among themselves except what their own imports and the other entries of the list demand (see Nested imports); where nothing decides, byte order of the path applies, and a later name overrides an earlier one. Name two files in the order you need as separate entries when it matters.
  • Skipped, not refused. A file named as a string anywhere in the same list, a file an earlier selector already stands for, and the importing file itself. A directory reached through several names (a symlink) is walked under each name; a file found twice is imported once, under the first path in byte order.
  • Refused. A directory the walk must list or enter and cannot (a missing read or search permission is refused, not skipped); a .yaml / .yml name that the selector matches but that is not a regular file (a broken link, a pipe); a subtree or a regex prefix that is not an existing directory. File names the selector does not match are never judged; directories are always entered.
  • No match is accepted and not reported — that is the point of a selector over files that may be absent. The price is that a typo in the pattern matches nothing and says nothing (a regex after its literal prefix; .yml files for a pattern that ends in \.yaml); check -v once.

Do not select over vendor/

Every file a selector matches becomes a layer of your configuration and can change any key, the fail threshold included. {subtree: vendor} hands that power to every installed package. For the same reason never select a name packages use for their own configuration (qmx.yaml): you would import configurations that were written for other projects. Import the packages you trust by path, or narrow a regex to the one file name an extension convention defines.

Nested imports

Any file read through imports may write imports itself — a shared standard can split itself without its consumer listing its parts. Built-in presets are included, though none writes it. A file given to --preset may not: it is refused, and the hint says to import the file from the configuration file or pass each as its own --preset.

# qmx.yaml
imports: [team/standard.yaml]
fail_on: error

# team/standard.yaml
imports: [strict, thresholds.yaml]   # team/thresholds.yaml

The layers are strict, team/thresholds.yaml, team/standard.yaml, qmx.yaml: what a file imports always sits below the file, and inside one list a later entry sits above an earlier one. A file reached twice is read once and placed once — the diamond below is the usual case:

Graph Layers, lowest first
F: [A, B] A B F
F: [A, B], A: [D], B: [D] (a diamond) D A B F
F: [D, A], A: [D] D A F
F: [A, D], A: [D] refused

The order is the C3 linearization (the method resolution order of Python), so a file means the same whichever file imports it (a selector written in an imported file can break that; see ADR 0140). Two refusals follow from it:

  • A cycle is refused at the entry that closes it, naming the files: … closes an import cycle: "cfg/a.yaml" imports "cfg/b.yaml" imports "cfg/a.yaml".
  • Contradictory precedence is refused on the file whose entries cannot all hold, naming each demand with the entry that makes it, and how each file was reached: F: [A, D] writes D above A, while A imports D and so needs A above D. Reorder the entries or drop one.

A refusal can come from a pair of files you never wrote together: F: [a, b, c], c: [b, d], d: [a] is refused because c puts a above b through d. The refusal prints that derived order.

Other refusals

Before the file is read: the same file twice in one list (two spellings or a symlink of one file count as the same), a file importing itself, a directory or other non-regular file, a URL, a file that is not .yaml or .yml, and an exact selector. imports is a list even for one file; imports: ~ and imports: [] import nothing.

What a later file can change

Override follows the merge policy of each key, so some edits have no spelling:

Node kind A later file…
scalar (fail_on, memory_limit, thresholds) replaces the value
map (cache, coupling, one rule's options) merges key by key
named map (rules, computed_metrics, architecture.allow) merges entry by entry
list (paths, only_rules, architecture.layers, framework_namespaces) replaces the whole list — cannot append
set (exclude, suppress_*, disabled_rules, exclude_health) adds — cannot remove a base's entry
shorthand (threshold) expands in the writing file: a later warning keeps the base's error
~ / {} "not written" / "changes nothing" — never a reset

Keep what a project may want to change — paths, exclude, suppress_* — in the root file rather than in a shared base, since a base's set entry cannot be taken back. A finding that a configured value matches nothing names the file that wrote it. When that file is a base in the project's Composer install directory (vendor/), an exclude, suppress_paths or suppress_namespaces entry, or a value of a rule's suppress_namespace_channels entry, that matches nothing is listed in projectScope.unjudgedValues instead of being reported — the project could not remove it (see Suppression rules).

Baselines and architecture.unmatched-type

An architecture.unmatched-type finding is identified by the type and its authored path, such as architecture.layers[0].implements[1]. Moving that criterion into an imported file, or adding a preset, keeps the finding and its baseline entry; moving it to another path re-identifies it.


Full Example

# Or start with a preset and customize:
# vendor/bin/qmx check src/ --preset=strict

paths:
  - src/

exclude:
  - subtree: vendor
  - subtree: tests/Fixtures

suppress_paths:
  - subtree: src/Entity
  - subtree: src/DTO

suppress_namespaces:
  - subtree: App\Tests

include_generated: false

format: summary
fail_on: error        # default — warnings shown but don't fail the build

cache:
  enabled: true
  dir: /home/user/.cache/qmx

parallel:
  workers: 4

coupling:
  framework-namespaces:
    - subtree: Symfony
    - subtree: Doctrine

exclude_health:
  - typing

disabled_rules:
  - code-smell.boolean-argument
  - duplication.clone

rules:
  complexity.ccn:
    suppress_namespaces:
      - subtree: App\Tests
    suppress_paths:
      - subtree: src/Generated
    callable:
      warning: 15
      error: 25

  size.method-count:
    warning: 25
    error: 40

CLI Options Override Config

Command-line options always take precedence over values in the configuration file. For example:

# Config says paths: [src/], but CLI overrides it
vendor/bin/qmx check lib/

# Add extra suppressed paths on top of config
vendor/bin/qmx check src/ --suppress-path='subtree:src/Generated'

This makes it easy to experiment without editing the config file.


How layers combine

Every source of configuration is a layer: the built-in defaults, what composer.json discovery finds, each preset in the order given, the files and presets qmx.yaml imports, qmx.yaml, and the command line — each one above the ones before it.

Each layer is read as it was written. Its keys are recognised and the form of every value it writes is judged in that layer, before anything is merged, so a misspelt key or a wrong value in a preset is refused even when your file overrides it. Then the layers are merged, each key by the policy it declares. A constraint needing the merged document — a layer name architecture.allow refers to or a computed metric referenced by a formula — is judged once, on the merged value. Formula syntax itself is checked in every writing layer. A refusal about a resolved value, and every warning, names the layer that wrote the value it is about; in --format=json that is the source field (see Output Formats). Finding's rules, only_rules and disabled_rules are declared in the same document. Rule forms, lower writes and paths retain their actual provenance; selection and effective bands are concluded before runtime publication.

Five rules describe the document engine; owners declare their value forms:

A value that is invalid without merged context is refused in every layer that writes it: the wrong shape, a forbidden empty value or a value outside a closed dictionary. A file's format: bogus or cache: {dir: ""} is still refused under a valid --format or --cache-dir. A constraint depending on other resolved values is judged on the winner. Text refusals name the writing layer; JSON publishes it in source.

This includes every coupling.framework_namespaces list's nonempty namespace patterns, valid regex syntax and 256-selector ceiling, and each architecture.layers list's unique names and patterns, membership criteria and template bindings. A higher list cannot hide those defects. Architecture allow references and cycles still require the merged set of layers.

  • ~ means "not written". A key written ~, or left empty (key:), leaves the value to the layer below. The key itself is still recognised: a misspelt key is refused even when its value is ~. Under a map keyed by names (computed_metrics, architecture.allow), name: ~ still has its name checked.
  • An empty map changes nothing. cache: {} or computed_metrics: {} over a preset keeps every value the preset wrote. An empty map does not reset a section to its defaults; write the values you want instead.
  • A list replaces or accumulates, by key. paths, only_rules, architecture.layers, one layer's target list under architecture.allow and a computed metric's levels are replaced whole by the last layer that writes them. An empty list is still a written replacement, subject to its owner's constraints: paths: [] is refused. exclude, suppress_paths, suppress_namespaces, disabled_rules and exclude_health accumulate: every layer adds to them. An item of a list is a value, not an unwritten key, so an item written ~ is refused.
  • A shorthand is expanded in the layer that wrote it, before any merge. threshold: 5 in a preset is warning: 5 and error: 5 in that preset, so a file that writes only warning: 3 over it gets warning 3 and error 5. Writing a shorthand beside one of its keys in the same layer is refused.
  • A key has three spellings: the snake_case, kebab-case and camelCase of its words — fail_on, fail-on, failOn. Any other spelling of the same words (Fail_On, FAILON, failon) is refused with the accepted one, for every key in the table below.
# preset
computed_metrics:
  computed.risk:
    formula: "m['complexity.ccn.max'] ?? 0"
    levels: [class]
    threshold: 20          # warning: 20 and error: 20, in the preset
# qmx.yaml
computed_metrics:
  computed.risk:
    warning: 10            # the formula, levels and error 20 still come from the preset
  health.typing:
    enabled: false         # the only way to remove a metric a lower layer wrote

What cannot be written

Three things have no spelling, deliberately:

  • Removing a key a lower layer wrote. A higher layer cannot delete a preset's computed metric or its architecture.allow entry for a layer. A computed metric is switched off with enabled: false; a layer's allow list can be replaced, [] included — which allows that layer nothing, rather than removing the entry.
  • Replacing a preset's whole set of computed metrics. Each metric merges on its own, by name.
  • Returning to the default without writing it. ~ and {} both keep the layer below; to get a default value back over a preset, write that value.

An empty map reset its section in earlier releases; see the changelog for what changed.

The declared rule section

The generated table reflects registered declarations and is refreshed by the same generator as other document policies. Finding consumes resolved nodes, not a second raw merge.

  • rules — options and level blocks merge by declared leaves. Shorthand expands in its writing layer; null/empty maps preserve lower writes. The rule boolean form changes enabled only. Restoring defaults requires explicit values.
# preset
rules: {complexity.ccn: {callable: {threshold: 5}}}
vendor/bin/qmx check src/ --preset=my-preset.yaml \
  --rule-opt='complexity.ccn:callable.warning=2'

The result is warning 2 from the command line and error 5 from the preset's shorthand — not the rule's compiled default.

Configuration warnings

A configuration that is legal but probably not what was meant is accepted with a warning rather than refused. Every command that reads the configuration prints its warnings to stderr, prefixed Warning:, and --format=json also lists them under configurationDiagnostics, each with the layers it is about. For example, only_rules: [] in qmx.yaml over a preset that filters the rules is lawful — an empty only_rules applies no filter — and says so:

Warning: "only_rules" is written empty in configuration file "qmx.yaml" and replaces the list preset "./ci-filter.yaml" wrote. An empty only_rules applies no rule filter: every enabled rule runs.

Every key

The table is generated from the declarations the configuration engine merges by. <name> stands for a name you choose, and [] for any item of a list: an item's keys are read from the layer that wrote the list and never merge. The owner of a key may still refuse a merged value the policy let through — a formula referencing an unknown computed metric, or a layer that allows a layer layers does not declare.

The table lists suppress-namespaces and suppress-paths under every rule, but for producers with project-scoped findings only they accept just an empty list or null; see Producers with project-scoped findings only. The same holds for suppress-namespace-channels, whose entries must name a channel that reports at the namespace level.

Key Value Across layers Written ~ Written empty ({}, [])
architecture map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
architecture.layers list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
architecture.layers[].name string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
architecture.layers[].patterns read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].suffix read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].attributes read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].member_attributes read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].implements read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].extends read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].match string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
architecture.layers[].pending boolean Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
architecture.layers[].exclude map Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Writes nothing: as if the key were absent.
architecture.layers[].exclude.patterns read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].exclude.suffix read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].exclude.attributes read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].exclude.member_attributes read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].exclude.implements read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].exclude.extends read by its owner Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Its owner decides.
architecture.layers[].exclude.match string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
architecture.allow map by name: names checked against architecture.layers once every layer is merged Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
architecture.allow.<name> list (item: read by its owner) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. Replaces the list below with an empty one.
architecture.coverage-gap string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
architecture.max_expanded_layers integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
cache map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
cache.dir string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
cache.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
computed_metrics.<name> map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
computed_metrics.<name>.description string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.formula string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.formulas map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
computed_metrics.<name>.formulas.class string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.formulas.namespace string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.formulas.project string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.inverted boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.levels list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
computed_metrics.<name>.warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
computed_metrics.<name>.threshold number Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
coupling map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
coupling.framework_namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
coupling.framework_namespaces[].exact string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
coupling.framework_namespaces[].subtree string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
coupling.framework_namespaces[].regex string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
disabled_rules list (item: string) Every layer adds its elements; duplicates collapse. Not written: the layer below stands. An item written ~ is refused. Adds nothing.
exclude list (item: map) Every layer adds its elements; duplicates collapse. Not written: the layer below stands. An item written ~ is refused. Adds nothing.
exclude[].exact string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
exclude[].subtree string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
exclude[].regex string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
exclude_health list (item: string) Every layer adds its elements; duplicates collapse. Not written: the layer below stands. An item written ~ is refused. Adds nothing.
fail_on string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
format string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
imports list (item: read by its owner) Read per file, in the root file and in any file read through imports; never merged across layers. Not written: the file imports nothing. An item written ~ is refused. The file imports nothing.
include_autoload_dev boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
include_generated boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
memory_limit string or integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
only_rules list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one. A warning says so when the list below was not empty.
parallel map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
parallel.workers integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
paths list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.annotation.directive map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.annotation.directive.unused-directive-severity string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.annotation.directive.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.annotation.directive.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.annotation.directive.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.annotation.directive.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.annotation.directive.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.circular-dependency map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.architecture.circular-dependency.direct-as-error boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.circular-dependency.ignore-relations list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.circular-dependency.max-cycle-size integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.circular-dependency.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.circular-dependency.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.architecture.circular-dependency.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.circular-dependency.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.circular-dependency.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.layer-declaration map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.architecture.layer-declaration.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.layer-declaration.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.architecture.layer-declaration.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.layer-declaration.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.layer-declaration.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.layer-violation map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.architecture.layer-violation.severity string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.layer-violation.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.layer-violation.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.architecture.layer-violation.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.layer-violation.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.layer-violation.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.unassigned-class map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.architecture.unassigned-class.mode string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.unassigned-class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.architecture.unassigned-class.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.architecture.unassigned-class.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.unassigned-class.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.architecture.unassigned-class.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.baseline.unused-entry map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.baseline.unused-entry.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.baseline.unused-entry.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.baseline.unused-entry.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.baseline.unused-entry.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.baseline.unused-entry.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.boolean-argument map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.boolean-argument.allowed-prefixes list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.boolean-argument.flag-promoted-properties boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.boolean-argument.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.boolean-argument.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.boolean-argument.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.boolean-argument.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.boolean-argument.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.constructor-overinjection map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.constructor-overinjection.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.constructor-overinjection.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.constructor-overinjection.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.constructor-overinjection.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.constructor-overinjection.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.constructor-overinjection.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.constructor-overinjection.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.constructor-overinjection.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.count-in-loop map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.count-in-loop.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.count-in-loop.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.count-in-loop.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.count-in-loop.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.count-in-loop.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.debug-code map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.debug-code.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.debug-code.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.debug-code.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.debug-code.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.debug-code.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.empty-catch map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.empty-catch.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.empty-catch.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.empty-catch.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.empty-catch.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.empty-catch.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.error-suppression map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.error-suppression.allowed-functions list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.error-suppression.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.error-suppression.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.error-suppression.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.error-suppression.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.error-suppression.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.eval map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.eval.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.eval.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.eval.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.eval.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.eval.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.exit map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.exit.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.exit.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.exit.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.exit.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.exit.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.goto map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.goto.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.goto.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.goto.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.goto.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.goto.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.identical-subexpression map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.identical-subexpression.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.identical-subexpression.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.identical-subexpression.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.identical-subexpression.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.identical-subexpression.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.long-parameter-list map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.long-parameter-list.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.long-parameter-list.vo-error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.long-parameter-list.vo-warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.long-parameter-list.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.long-parameter-list.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.long-parameter-list.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.long-parameter-list.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.long-parameter-list.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.long-parameter-list.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.long-parameter-list.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.long-parameter-list.vo-threshold integer Shorthand for vo-warning and vo-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.superglobals map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.superglobals.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.superglobals.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.superglobals.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.superglobals.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.superglobals.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.unreachable-code map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.unreachable-code.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.unreachable-code.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.unreachable-code.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.unreachable-code.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.unreachable-code.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.unreachable-code.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.unreachable-code.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.unreachable-code.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.unused-private map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.code-smell.unused-private.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.code-smell.unused-private.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.code-smell.unused-private.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.unused-private.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.code-smell.unused-private.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.cohesion.lcom map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.cohesion.lcom.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.cohesion.lcom.exclude-methods list (item: string) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.cohesion.lcom.exclude-readonly boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.cohesion.lcom.min-methods integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.cohesion.lcom.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.cohesion.lcom.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.cohesion.lcom.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.cohesion.lcom.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.cohesion.lcom.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.cohesion.lcom.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.cohesion.lcom.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.complexity.ccn.callable map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.complexity.ccn.callable.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.callable.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.callable.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.callable.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.class map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.complexity.ccn.class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.class.max-error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.class.max-warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.class.threshold integer Shorthand for max-warning and max-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.ccn.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.complexity.ccn.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.ccn.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.ccn.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.ccn.threshold integer Shorthand for callable.threshold: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.complexity.cognitive.callable map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.complexity.cognitive.callable.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.callable.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.callable.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.callable.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.class map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.complexity.cognitive.class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.class.max-error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.class.max-warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.class.threshold integer Shorthand for max-warning and max-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.cognitive.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.complexity.cognitive.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.cognitive.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.cognitive.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.cognitive.threshold integer Shorthand for callable.threshold: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.complexity.npath.callable map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.complexity.npath.callable.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.callable.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.callable.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.callable.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.class map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.complexity.npath.class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.class.max-error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.class.max-warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.class.threshold integer Shorthand for max-warning and max-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.npath.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.complexity.npath.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.npath.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.npath.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.npath.threshold integer Shorthand for callable.threshold: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.wmc map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.complexity.wmc.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.wmc.exclude-data-classes boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.wmc.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.wmc.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.complexity.wmc.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.complexity.wmc.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.wmc.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.wmc.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.complexity.wmc.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.computed map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.computed.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.computed.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.computed.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.computed.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.computed.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.cbo map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.coupling.cbo.class map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.coupling.cbo.class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.class.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.class.scope string The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.class.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.class.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.namespace map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.coupling.cbo.namespace.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.namespace.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.namespace.min-class-count integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.namespace.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.namespace.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.coupling.cbo.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.cbo.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.cbo.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.cbo.threshold integer Shorthand for class.threshold and namespace.threshold: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.warning integer Shorthand for class.warning and namespace.warning: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.error integer Shorthand for class.error and namespace.error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.cbo.scope string Shorthand for class.scope: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.class-rank map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.coupling.class-rank.error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.class-rank.warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.class-rank.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.class-rank.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.coupling.class-rank.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.class-rank.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.class-rank.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.class-rank.threshold number Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.distance map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.coupling.distance.include-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.distance.max-distance-error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.distance.max-distance-warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.distance.min-type-count integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.distance.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.distance.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.coupling.distance.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.distance.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.distance.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.distance.threshold number Shorthand for max-distance-warning and max-distance-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.coupling.instability.class map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.coupling.instability.class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.class.max-error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.class.max-warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.class.min-afferent integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.class.threshold number Shorthand for max-warning and max-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.namespace map Merged key by key; a written empty map changes nothing. Not written: the layer below stands. Changes nothing.
rules.coupling.instability.namespace.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.namespace.max-error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.namespace.max-warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.namespace.min-afferent integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.namespace.min-type-count integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.namespace.threshold number Shorthand for max-warning and max-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.coupling.instability.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.instability.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.instability.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.instability.threshold number Shorthand for class.threshold and namespace.threshold: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.max-warning number Shorthand for class.max-warning and namespace.max-warning: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.instability.max-error number Shorthand for class.max-error and namespace.max-error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.unmatched-framework-namespace map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.coupling.unmatched-framework-namespace.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.coupling.unmatched-framework-namespace.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.coupling.unmatched-framework-namespace.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.unmatched-framework-namespace.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.coupling.unmatched-framework-namespace.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.data-class map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.data-class.exclude-exceptions boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.exclude-promoted-only boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.exclude-readonly boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.min-members integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.wmc-threshold integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.woc-threshold integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.data-class.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.data-class.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.data-class.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.data-class.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.dit map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.dit.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.dit.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.dit.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.dit.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.dit.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.dit.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.dit.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.dit.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.god-class.class-loc-threshold integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.exclude-readonly boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.lcom-threshold integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.min-criteria integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.min-methods integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.tcc-threshold number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.wmc-threshold integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.god-class.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.god-class.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.god-class.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.god-class.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.noc map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.noc.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.noc.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.noc.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.noc.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.noc.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.noc.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.noc.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.noc.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.param map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.type-coverage.param.error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.param.warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.param.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.param.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.type-coverage.param.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.param.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.param.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.param.threshold number Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.property map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.type-coverage.property.error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.property.warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.property.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.property.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.type-coverage.property.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.property.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.property.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.property.threshold number Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.return map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.design.type-coverage.return.error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.return.warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.return.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.design.type-coverage.return.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.design.type-coverage.return.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.return.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.return.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.design.type-coverage.return.threshold number Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.discovery.unmatched-exclude map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.discovery.unmatched-exclude.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.discovery.unmatched-exclude.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.discovery.unmatched-exclude.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.discovery.unmatched-exclude.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.discovery.unmatched-exclude.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.duplication.clone map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.duplication.clone.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.duplication.clone.min-lines integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.duplication.clone.min-tokens integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.duplication.clone.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.duplication.clone.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.duplication.clone.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.duplication.clone.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.duplication.clone.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.cohesion map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.health.cohesion.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.health.cohesion.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.health.cohesion.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.cohesion.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.cohesion.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.complexity map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.health.complexity.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.health.complexity.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.health.complexity.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.complexity.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.complexity.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.coupling map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.health.coupling.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.health.coupling.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.health.coupling.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.coupling.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.coupling.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.maintainability map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.health.maintainability.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.health.maintainability.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.health.maintainability.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.maintainability.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.maintainability.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.overall map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.health.overall.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.health.overall.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.health.overall.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.overall.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.overall.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.typing map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.health.typing.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.health.typing.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.health.typing.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.typing.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.health.typing.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.maintainability.mi map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.maintainability.mi.error number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.maintainability.mi.exclude-tests boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.maintainability.mi.min-statements integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.maintainability.mi.warning number The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.maintainability.mi.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.maintainability.mi.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.maintainability.mi.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.maintainability.mi.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.maintainability.mi.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.maintainability.mi.threshold number Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.security.command-injection map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.security.command-injection.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.security.command-injection.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.security.command-injection.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.command-injection.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.command-injection.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.hardcoded-credentials map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.security.hardcoded-credentials.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.security.hardcoded-credentials.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.security.hardcoded-credentials.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.hardcoded-credentials.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.hardcoded-credentials.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.sensitive-parameter map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.security.sensitive-parameter.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.security.sensitive-parameter.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.security.sensitive-parameter.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.sensitive-parameter.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.sensitive-parameter.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.sql-injection map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.security.sql-injection.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.security.sql-injection.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.security.sql-injection.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.sql-injection.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.sql-injection.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.xss map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.security.xss.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.security.xss.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.security.xss.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.xss.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.security.xss.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.class-count map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.size.class-count.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.class-count.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.class-count.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.class-count.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.size.class-count.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.class-count.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.class-count.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.class-count.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.method-count map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.size.method-count.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.method-count.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.method-count.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.method-count.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.size.method-count.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.method-count.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.method-count.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.method-count.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.property-count map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.size.property-count.error integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.property-count.exclude-promoted-only boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.property-count.exclude-readonly boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.property-count.warning integer The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.property-count.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.size.property-count.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.size.property-count.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.property-count.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.property-count.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.size.property-count.threshold integer Shorthand for warning and error: expanded in the layer that wrote it, before any merge; each key then merges on its own. Writing it beside one of them in the same layer is refused. Not written: the layer below stands. Refused: a scalar is expected.
rules.suppression.configuration map Merged key by key; a written empty map changes nothing. The name is judged; the body stays with the layer below. Changes nothing.
rules.suppression.configuration.enabled boolean The last layer that writes the value wins. Not written: the layer below stands. Refused: a scalar is expected.
rules.suppression.configuration.suppress-namespace-channels map by name: a name judged by the section's grammar in the layer that wrote it Merged entry by entry, keyed by name; each entry merges by its own policy. Not written: the layer below stands. Changes nothing.
rules.suppression.configuration.suppress-namespace-channels.<name> list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. The name is judged; the body stays with the layer below. An item written ~ is refused. Replaces the list below with an empty one.
rules.suppression.configuration.suppress-namespaces list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
rules.suppression.configuration.suppress-paths list (item: map) The last layer that writes the list replaces it whole; an empty list replaces too. Not written: the layer below stands. An item written ~ is refused. Replaces the list below with an empty one.
suppress_namespaces list (item: map) Every layer adds its elements; duplicates collapse. Not written: the layer below stands. An item written ~ is refused. Adds nothing.
suppress_namespaces[].exact string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
suppress_namespaces[].subtree string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
suppress_namespaces[].regex string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
suppress_paths list (item: map) Every layer adds its elements; duplicates collapse. Not written: the layer below stands. An item written ~ is refused. Adds nothing.
suppress_paths[].exact string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
suppress_paths[].subtree string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.
suppress_paths[].regex string Read from the layer that wrote the list; never merged across layers. Not written: as if the key were absent. Refused: a scalar is expected.

Configuration Validation

Qualimetrix validates your configuration file and reports clear errors for common mistakes.

Unknown keys

Any unrecognized key — at the root level or inside a section — produces an error with a suggestion:

Configuration error: Unknown key "parallel.workes" in configuration file "qmx.yaml" (did you mean "workers"?). Accepted keys: workers.
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

A key is unknown whatever its value, ~ included, and in whichever layer it is written: a preset's typo is refused like your file's. A key written in a spelling other than its three accepted ones is refused with the accepted spelling:

Configuration error: Key "Fail_On" in configuration file "qmx.yaml" is not written in an accepted spelling; write "fail_on" (its snake_case, camelCase and kebab-case spellings are accepted).
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

The same spelling rule applies to rule-option keys and level segments in --rule-opt. A wrong-case rule owner suggests the exact registered name. CLI refusals include the complete authored flag/value expression alongside the option source.

Type errors

Symfony YAML reads unquoted +2 and 2.0 as floats. Integer options refuse both in the file, --rule-opt and dedicated aliases, name the parsed float and explain that an integer should be written as 2. File refusals name the path; CLI refusals also retain the complete authored expression. Quoted "+2" stays a string. Exponent notation and overflow remain refused by integer options.

If a value has the wrong type, you'll get a clear message instead of silent fallback to defaults:

Configuration error: "cache.enabled" in configuration file "qmx.yaml" must be boolean, got string.
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

Unknown rule names

Misspelled rule names in the rules: section are rejected:

Configuration error: Rule option owner "complexty.ccn" does not match any registered producer rule. Did you mean "complexity.ccn"?
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

Unknown rule option keys

An option key a rule does not have is a configuration error at every depth it can be written at — the run stops with exit code 3 and nothing is analyzed:

Configuration error: Unknown key "rules.complexity.ccn.warning_threshold" in configuration file "qmx.yaml". Accepted keys: callable, class, enabled, suppress-namespace-channels, suppress-namespaces, suppress-paths, threshold.
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

Inside a level slot the message names the slot, because the allowed set is per level and not per rule:

Configuration error: Unknown key "rules.complexity.ccn.class.warning" in configuration file "qmx.yaml". Accepted keys: enabled, max-error, max-warning, threshold.
Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt

--rule-opt rejects the same undeclared keys with exit code 3, naming its own flag (Source: option --rule-opt.); its wording and hints can differ from YAML.

The key keeps its authored spelling

An unknown key keeps its separators: max_warnign is printed as "max_warnign", without folding. File refusals name the full authored key path and file; CLI refusals name the flag. Allowed keys are listed in the canonical kebab spelling of the declaration.

The shape of a value

The two rules below hold for every key in this document — the roots, the sections, the rules: subtree and the level slots inside it alike. They are not a property of rule options; rule options are simply where you meet them most often.

Every key declares the shape its value may take. A value of another shape ends the run with exit code 3. It is never converted into something usable, and it is never dropped in favour of the default while the run reports success. Every source the value arrives from is judged, not only the one that wins: a wrong format: or cache_dir: in a file is refused even when the command line overrides it, because a value nobody will use is still a value somebody wrote:

Configuration error: "rules.complexity.ccn.callable.warning" in configuration file "qmx.yaml" must be integer at least 0, got string.
Configuration error: "only_rules" in configuration file "qmx.yaml" must be a list, got a map.
Configuration error: "cache" in configuration file "qmx.yaml" must be a map, got a list.

These are three separate runs, one mistake apiece — a real run stops at its own first error. Each one's stderr ends with the same documentation pointer line shown throughout this page (e.g. Docs: https://qualimetrix.dev · AI agents: https://qualimetrix.dev/llms.txt); it is omitted above so the three messages can be compared side by side.

The shapes a key can ask for, in the words the refusal uses:

Shape Accepts
a boolean true / false
a non-negative whole number 15 or 0 — not 10.5, not "15", not -1
a non-negative number 15, 10.5 or 0 — not -0.5
a number any number of either sign (computed-metric thresholds only)
a string any string, the empty one included
a non-empty string a string with at least one non-blank character
a list of X a YAML sequence, every element of shape X
a map of X a YAML mapping you name the keys of, every value of shape X
a block of options a mapping whose own keys another declaration answers for

Six consequences are worth spelling out, because each of them used to pass unnoticed:

  • A quoted number is a string. warning: "15" is refused where a whole number is declared; write warning: 15. This is a YAML-only distinction — values that arrive on the command line are text by construction and are converted before their shape is judged, so --rule-opt="size.method-count:threshold=25" and --rule-opt="complexity.ccn:enabled=false" are unaffected.
  • A whole number is not a fraction — except for the keys named here, which declare "a non-negative number". warning: 10.5 is refused where a whole number is declared, and most thresholds in this document declare exactly that: a whole number. The keys below declare "a non-negative number" instead, and therefore accept a fraction exactly as written, because each one measures a continuously-valued metric rather than counting something: the maintainability index (maintainability.mi.error / .warning / .threshold), instability (coupling.instability.max-error / .max-warning / .threshold, the same three at the class. and namespace. level slots too), distance from the main sequence (coupling.distance.max-distance-error / .max-distance-warning / .threshold), ClassRank (coupling.class-rank.error / .warning / .threshold), type coverage (design.type-coverage.param.error / .warning / .threshold, the same three under .property. and .return.) and the TCC threshold on design.god-class.tcc-threshold. This is a property of each key's own declared shape, not of its rule or family as a whole: keys living right beside an accepting one stay whole numbers and refuse a fraction, because they count something instead of measuring it — coupling.distance.min-type-count, coupling.instability.min-afferent (at every level slot) and coupling.instability.namespace.min-type-count are each a type or file count, not a ratio.
  • A threshold or a count is never negative. Every numeric option under rules: is a count or a boundary on a measurement that cannot be negative, and a negative boundary does not tighten a rule, it inverts it: warning: -1 on size.method-count would report every class. It is refused with the value itself, from the file and from --rule-opt alike, and a threshold: -1 shorthand is named as threshold, the key that was written. Zero is accepted. A computed metric's warning / error / threshold keep both signs, because its formula is yours and may well be negative.
  • A list and a map are not interchangeable. only_rules: {a: complexity.ccn} and exclude_methods: {a: getName} are refused; write only_rules: [complexity.ccn] and exclude_methods: [getName]. The same in the other direction: cache: [dir] is refused, because cache: is a section of named keys.
  • Selector lists contain one-entry mappings, not scalar shortcuts. Write - exact: '2024' for a directory literally named 2024; a bare scalar is refused for suppress_paths, suppress_namespaces, exclude, framework namespaces, and per-rule selector lists alike.
  • The empty string is a shape of its own. It is refused wherever a non-empty value is required, on the command line as well: --fail-on=, --format=, --cache-dir= and --memory-limit= each name what they expected instead of quietly taking the default.

A key written with no value

Writing a key and leaving it empty — key: or the explicit YAML null key: ~ — means the default is taken for that key's own value, at every depth and in every section, rules: included:

cache: ~                 # same as not writing cache:
coupling: ~              # same as not writing coupling:
cache:
  dir: ~                 # same as not writing dir:
rules:
  complexity.ccn:
    enabled: ~           # same as not writing enabled:
    callable: ~          # same as not writing callable:

That covers the keys inside rules: that choose how a rule is read, not only those whose value is read. A threshold key selects the shorthand form of a hierarchical rule — threshold: on complexity.ccn, complexity.cognitive and complexity.npath; threshold:, warning: or error: on coupling.cbo; threshold:, max_warning: or max_error: on coupling.instability — and it is the value written there that selects it. A ~ writes no value, so it selects nothing and the callable: / class: / namespace: blocks beside it are read exactly as if the key were not there:

rules:
  coupling.cbo:
    warning: ~       # same as omitting it
    class:
      warning: 0     # read
      error: 0

For the same reason threshold: ~ written beside warning: / error: names no second mode, so there is nothing for it to be mixed with:

rules:
  cohesion.lcom:
    threshold: ~     # no value, so no mode
    warning: 5       # graduated mode, as if threshold: had not been written

Two values are still two modes, and that is still a configuration error:

rules:
  cohesion.lcom:
    threshold: 3     # Configuration error, exit 3:
    warning: 5       # Cannot mix "threshold" with "warning"/"error"

An element of a list is the one place this does not apply, and for a reason: an element is a value, not a key that was left unwritten, so there is nothing for it to mean. A ~ element is refused, with its index, in every list outside rules: and in every list a rule's options declare:

rules:
  complexity.ccn:
    suppress_namespaces:
      - subtree: App\Legacy
      - ~              # refused: exit 3

Editor support

Qualimetrix ships a JSON Schema of its configuration file, qmx.schema.json. Point an editor that validates YAML against JSON Schema at it, and while you write qmx.yaml you get:

  • completion of keys, rule names and each rule's options;
  • each rule's description as a hint;
  • highlighting of shape errors: an unknown key, a value of the wrong type, a number below its minimum, a word outside a fixed list.

The schema checks the shape of one file, not its meaning. qmx stays the final judge. The editor does not check formulas, selectors, regular expressions, paths, references to declared architecture layers, constraints that depend on other values, or anything that depends on how presets and your file combine. It does catch a shorthand written beside its own target in one object, such as threshold together with warning. A file the editor accepts can still be refused by qmx check.

The reverse is what the schema is built to avoid: it is generated from the same declarations qmx reads, and it is tested never to flag a file qmx accepts — except where the editor's YAML parser reads a value differently (see Limitations).

Where to get the schema

Source Use it when
vendor/qualimetrix/qualimetrix/qmx.schema.json Recommended. You installed Qualimetrix with Composer: the file always matches the installed version.
https://raw.githubusercontent.com/qualimetrix/qualimetrix/vX.Y.Z/qmx.schema.json You need a fixed address, for example with the phar, which does not carry the schema. Replace vX.Y.Z with your installed version; the content at this address never changes.
https://github.com/qualimetrix/qualimetrix/releases/latest/download/qmx.schema.json You always run the latest release. This address redirects to the newest release's asset; whether every editor follows the redirect has not been verified.

Releases published before the schema was introduced have no file at these addresses.

VS Code

Install the YAML extension by Red Hat and make this the first line of qmx.yaml, with the address or a path relative to the file:

# yaml-language-server: $schema=vendor/qualimetrix/qualimetrix/qmx.schema.json
paths: [src]

qmx.yaml.example already starts with such a line. The path is resolved relative to the config file, so it works when the file lies in the project root next to vendor/. An imported file needs its own modeline, with the path written relative to that file (# yaml-language-server: $schema=../vendor/qualimetrix/qualimetrix/qmx.schema.json for config/a.yaml).

PhpStorm

Open Settings → Languages & Frameworks → Schemas and DTDs → JSON Schema Mappings, add a mapping, choose vendor/qualimetrix/qualimetrix/qmx.schema.json (or one of the addresses above) as the schema, and add qmx.yaml, qmx.yml, qmx.dist.yaml and qmx.dist.yml as files mapped to it. A config file with another name, passed through --config or a preset, is bound the same way: add its name or path to the mapping (or put the modeline from the VS Code section on its first line). The same goes for a file the root imports: the editor binds a schema to a file by its name, not by the file that imports it, so config/*.yaml needs its own mapping or a modeline. If the dialog asks for a schema version, choose JSON Schema version 7.

Limitations

  • Different YAML parsers. qmx reads YAML with Symfony YAML; editors use their own parser (the Red Hat extension follows YAML 1.2). A scalar the two type differently — 1_000, 0755, a date — can be accepted by one and flagged by the other. Where they disagree on such a value, qmx check is right.
  • Match the versions. Use the schema of the qmx version you run. A newer release may remove keys your version still accepts, and an older schema does not know keys added since.

What's Next?

See the CLI Options reference for the complete list of command-line options.

Declared rule forms and prepared execution

rules is a declared document section. Every registered producer names its accepted root options, level slots, value forms and threshold bands. Each writing layer is checked before merging, even when a later layer overrides it. There is no permissive raw option bag or second constructor-reflected vocabulary. Unknown owners, retired keys and invalid spellings refuse with their authored producer/key path and source before Discovery.

A rule boolean writes only enabled. true preserves thresholds, exclusions and each level's own switch; false disables every level. A rule or level {} writes nothing, and ~ leaves the lower value. No empty-body reset restores defaults. To restore a default over an earlier layer, write its value explicitly. A level requires its own declared map, such as class: {enabled: false}, rather than a rule boolean.

Shorthands expand in their own layer. Writing threshold and one of its band halves in the same layer refuses. A top hierarchical shorthand conflicts only with an explicit write to the same expanded leaf; independent children coexist, and across layers expanded leaves merge. Complexity's top shorthand changes callable only and preserves class; CBO and instability spread their flat bands to class and namespace. A written NPath class band activates without a redundant true switch. Explicit class.enabled: false still wins. Numeric defaults and formulas do not change.

After merging, owners build typed options for every producer, including inactive ones, and validate effective warning/error ordering against written and default halves. An invalid band reports the real contributing sources. Selection is then concluded with option activity before any runtime state is published. A failed preflight leaves no ready snapshot and publishes no partial producer options.

enabled: true is an authored exact enable, not disposable decoration: it can cancel a lower disable and must be admitted by the effective only filter. Keep it when enabling is intended. A mode of ignore remains inactive: explicitly enabling that inactive producer refuses, while enabled:false with a reportable mode is lawful. See Rule selection for the layer/specificity, empty-selection and channel-level rules.

Selection and built options use the same immutable invocation channel snapshot, including authored computed definitions. Producer metadata and finding channels are different sets. A producer may have several channels; dynamic channel names and declared levels are not a hardcoded default catalogue.