A Reference

Every rule,
with a specimen
from the field.

A reader's guide to the rules that ship by default in phr-mcp init --packs rust — the language-agnostic platform packs are included automatically, and the context pack installs scaffolding rather than rules. Each entry carries its predicate, its severity, a one-line distillation, and a worked example drawn from real-world Rust code. The confidence pack adds two gate rules that count grounded build/test/known-bug signals; the journey pack ships taggers and aggregator-fact references that let projects write their own trajectory rules. The structural pack reasons over a code graph built at the hook boundary, flagging untested panicking paths and import cycles in the file you are editing.

Packs catalogued
14
Rules shipped
95
Blocks (pre)
15
Hook warnings
50
Audit-only
30
Field examples
24

How to read this

Each rule is presented as a labelled specimen. The circular glyph encodes the severity at a glance: a red ✕ is a block (pre-phase, exit 2, the host refuses the action); an amber ! is a warning (post-phase, exit 1, the action applies but the operator is told); a slate ○ is audit-only (silent at hook time, surfaced only by phr-mcp audit).

Tags beneath each rule name show its phase and whether it participates in audits. The italic line is the rule's one-sentence point. From the field blocks show synthetic but plausible Rust code that would trip the rule, paired with a refactor that satisfies it.

Examples are illustrative, not extracted verbatim. They are written to clarify the rule, not to document any one project's actual state.

documents the default packs as of v0.35.0

llm pack

blockprellm

enforce-no-pre-existing-issue

Don't deflect with 'pre-existing issue'. Either fix it as part of this change, defer with a clear rationale, or drop the disclaimer.

new_content_contains
blockprellm

enforce-no-not-from-our-changes

Drop the 'not from our changes' disclaimer. Name the issue and decide: fix or defer.

new_content_contains
blockprellm

enforce-no-not-caused-by-our

Drop the 'not caused by our' disclaimer. Own the fix or own the decision to defer.

new_content_contains
blockprellm

enforce-no-should-work-claim

Avoid claiming a fix is complete without evidence. Run the verification (test, manual exercise, traced call chain) before reporting, or explicitly label the work 'untested' so the human knows to check.

new_content_contains
blockprellm

enforce-no-should-be-fixed-claim

Don't make repair claims without verifying. Run the failing case end-to-end before reporting a fix; otherwise mark it 'untested' so the user knows to verify.

new_content_contains
warnprellm

nudge-verify-before-commit

About to commit. Trace the call chain end-to-end before reporting done. Half-fixes where one layer is wired but another is not are a recurring failure mode.

bash_command_matches + __script__
warnprellm

llm-warn-git-add-all

Stage files explicitly — git add -A / git add . sweeps unrelated changes into the commit. List the files you actually changed.

bash_command_matches
warnprellm

llm-warn-kill-build

Builds are I/O-bound: a rustc at 0% CPU is usually in disk-wait, not hung. Give it time or check `ps` state before killing the build.

bash_command_matches
blockprellm

block-agent-write-to-verification-allowlist

The verification allowlist is a trust anchor: approvals are human-principal acts (SPEC-C S3). An approval written by the agent is not a review — ask the human to approve the artifact.

project_path_is
blockprellm

block-agent-write-to-verification-optin

`.phronesis/verification.json` is the verification opt-in (including `raw_execution`) and a trust anchor (SPEC-C S1). Only the human changes it.

project_path_is
blockprellm

block-agent-write-to-verification-templates

`verification/templates/` is a trust anchor (SPEC-C S1/S3): templates and the devcontainer declaration are human-principal content. Propose the change to the human instead of writing it.

project_path_under
warnprellm

warn-agent-shell-write-to-trust-anchors

This command appears to write a verification trust anchor (`.phronesis/verification-allowlist.json`, `.phronesis/verification.json`, or `verification/templates/`). Those are human-principal acts (SPEC-C S1/S3) — reading them is fine; changing them is the human's call. Stop and ask unless the human asked for this change.

bash_command_code_matches

rust pack

blockprerust

enforce-no-unwrap-in-src

Avoid .unwrap() in src/ — use ? for error propagation, or expect() with a clear message if truly unreachable.

rust_governed_invocation + file_path_matches
blockprerust

enforce-no-todo-in-src

Don't ship todo!() in src/ — finish the implementation or split it into a tracked task.

rust_governed_invocation + file_path_matches
blockprerust

enforce-no-panic-in-src

Avoid panic!() in src/ — return a Result and let the caller decide.

rust_governed_invocation + file_path_matches
blockprerust

enforce-no-unimplemented-in-src

Avoid unimplemented!() in src/ — implement the path or remove it.

rust_governed_invocation + file_path_matches
blockprerust

enforce-no-result-string-error

`?fn` in ?file returns Result<_, String>. Define a proper error enum with thiserror.

function_returns_result_string
warnprerust

warn-dbg-in-src

dbg!() in src/ — remove before committing, or use tracing::debug!() for diagnostics that stay.

rust_governed_invocation + file_path_matches
warnpostrust

warn-rust-public-fn-takes-string-ref

Public `?fn` takes `?param: &String` — prefer `&str` for ergonomics and to avoid forcing callers to own a String.

function_is_public + function_param_type
warnpostrust

warn-rust-function-param-count-high

Function `?fn` in ?file has ?count parameters. Consider grouping related params into a struct (builder/options pattern) or splitting the function — long signatures correlate with God-function debt.

function_param_count_high
warnauditrust

audit-file-loc-high

File exceeds 800 lines — consider splitting into focused submodules. Long files correlate with God-object debt and slow down navigation. (Scoped to src/; test blocks excluded from the count; a top-of-file `//! phronesis-allow: audit-file-loc-high <reason>` doc-comment exempts intentional god-files.)

file_extension_is + file_path_matches + file_line_count_above
warnpostrust

warn-rust-public-fn-takes-vec-ref

Public `?fn` takes `?param: &Vec<T>` — prefer `&[T]` for ergonomics; a slice accepts arrays, slices, and Vecs alike. From the patterns guide §API Design 1.

function_is_public + function_param_is_vec_ref
warnprerust

warn-cargo-build-without-workspace

Running `?cmd` without `--workspace` only checks part of the workspace. Use `cargo <subcommand> --workspace --tests --examples` to catch sibling-crate breakage, or pass `-p <crate>` if scope was intentional.

cargo_command_lacks_workspace
warnprerust

warn-clone-heavy

`?fn` in ?file calls .clone() ?count times — review whether references or borrowed slices would work.

function_clone_count_high
warnpostrust

warn-pub-fn-missing-doc

Public fn `?fn` in ?file has no doc comment — public items should carry a `///` doc comment explaining what they do (Rust API Guidelines C-DOC).

pub_fn_without_doc_comment + file_path_matches
warnpostrust

warn-empty-test

Test `?fn` in ?file has no assertions or `?` propagation — a placeholder test that always passes hides regressions.

test_without_assertion
warnprerust

warn-deref-for-non-pointer-type

`impl Deref for` — Deref polymorphism is an anti-pattern for non-pointer types. Reserve Deref for smart-pointer wrappers (Box/Arc/Rc); for other types, prefer explicit delegation methods so the API surface is intentional.

rust_trait_impl + file_extension_is
warnauditrust

audit-manual-err-return

Manual `=> return Err(...)` in a match arm — the `?` operator usually replaces this whole shape. Surface during one-time audit sweeps; deliberately silent at hook time so in-progress refactors aren't blocked.

rust_governed_match_arm + file_extension_is
warnauditrust

audit-newtype-id-string

Field named `*_id: String` — consider a newtype like `StateId(String)` for type safety so one ID kind can't be passed where another is expected. From the patterns guide §Design Patterns 2 (Newtype Pattern). (Scoped to src/ — test fixtures are exempt. A `///` doc-comment immediately above the field marks an intentional string ID, e.g. one crossing a JSON registry boundary, as an accepted exception.)

new_content_contains + file_extension_is + file_path_matches
warnauditrust

audit-newtype-id-u64

Field named `*_id: u64` — consider a newtype like `UserId(u64)` to prevent mixing different ID types. From the patterns guide §Design Patterns 2 (Newtype Pattern). (Scoped to src/ — test fixtures are exempt.)

rust_primitive_id_field + file_extension_is + file_path_matches
warnauditrust

audit-if-let-opportunity-none-empty

`match` with a `None => {}` arm — `if let Some(x) = ...` is usually clearer. From the patterns guide §Idioms 2.

rust_governed_match_arm + file_extension_is
warnauditrust

audit-if-let-opportunity-err-empty

`match` arm `Err(_) => {}` silently swallows errors. Either handle the error (log/return) or use `if let Ok(x) = ...` to make the intent explicit.

rust_governed_match_arm + file_extension_is
blockprerust

block-panic-in-drop-impl

Panicking construct (?construct) inside `Drop::drop` for `?type` — a panic that occurs during unwind inside Drop::drop aborts the whole process (std::process::abort) rather than failing gracefully. Log and swallow the error in drop() instead of panicking.

rust_panic_in_drop + file_extension_is
blockprerust

block-deny-warnings-attribute

`#![deny(warnings)]` breaks builds on toolchain upgrades, since each rustc release introduces new warnings. Move the policy to CI with `RUSTFLAGS="-D warnings"` instead. From the patterns guide §Anti-patterns (deny-warnings).

rust_governed_attribute + file_extension_is
warnprerust

warn-public-fn-takes-box-ref

Parameter type `&Box<T>` adds a useless layer of indirection — prefer `&T` directly. From the patterns guide §Idioms (borrowed-types-for-arguments).

function_param_is_box_ref + file_extension_is
warnprerust

warn-expect-with-empty-message

`.expect("")` is strictly worse than `.unwrap()` — same panic, no explanation of the invariant. Either supply a real message or use `.unwrap()` and let the existing rule flag it.

rust_governed_invocation + file_path_matches
warnauditrust

audit-rc-refcell-in-src

`Rc<RefCell<T>>` is the textbook 'fighting the borrow checker' shape — often a signal that an arena, index-based references, or a redesigned ownership model would be a better fit. Confirm intent.

rust_rc_refcell_type + file_path_matches
warnauditrust

audit-string-concat-with-plus

String concatenation with `" + &` — prefer `format!("{}{}", a, b)` for readability and to avoid intermediate allocations. From the patterns guide §Idioms (concat-format).

new_content_contains + file_extension_is
warnauditrust

audit-allow-dead-code-in-src

`#[allow(dead_code)]` in src/ — either delete the code or add a `///` doc-comment immediately above explaining why it's kept (planned API, generic-constraint trick, intentional placeholder). Documented exceptions are not flagged.

new_content_contains + file_path_matches
warnauditrust

audit-env-set-var-in-src

`env::set_var(` in src/ — mutating process environment variables is unsound under concurrent reads (which is why edition 2024 marks the call unsafe). Verify the call site is genuinely single-threaded, or refactor to pass configuration explicitly through function arguments / a context struct. Tests where you control the thread count are usually fine; library code almost never is.

rust_governed_invocation + file_path_matches
warnauditrust

audit-rust-let-binding-count-high

`?fn` in ?file has ?count outer-scope `let` bindings — consider scoping intermediate temporaries into a block (`let result = { let raw = ...; let parsed = ...; ... }`) so only the final value is visible to the rest of the function. Block pattern: John Nunley, 'Rust's Block Pattern' (Dec 2025). (Scoped to src/ — examples/benches/tests are not production code and are exempt.)

file_path_matches + function_let_binding_count_high
warnauditrust

audit-rust-let-mut-count-high

`?fn` in ?file has ?count outer-scope `let mut` declarations — consider John Nunley's block pattern: wrap the mutation in `let x = { let mut tmp = ...; ...; tmp }` so the surrounding scope sees an immutable binding. Block pattern: John Nunley, 'Rust's Block Pattern' (Dec 2025). (Scoped to src/ — examples/benches/tests are not production code and are exempt.)

file_path_matches + function_let_mut_count_high
warnauditrust

audit-rust-sync-lock-across-await

`?fn` in ?file keeps std synchronization guard `?guard` in scope across `.await` — close the guard's lexical scope before awaiting. A synchronous Mutex/RwLock can block the executor and often makes the future non-Send.

rust_sync_lock_guard_across_await
warnauditrust

audit-rust-unsafe-without-safety-comment

Unsafe block in `?fn` (?file) has no nearby `SAFETY:` explanation — document the invariant that makes the operation sound so reviewers can verify it.

rust_unsafe_without_safety_comment
warnprerust

warn-rust-blocking-call-in-async

Async function `?fn` in ?file calls blocking `?callee` directly — use the async runtime's equivalent or isolate the operation with `spawn_blocking`.

rust_async_blocking_call

rhai pack

blockprerhai

block-rhai-inline-eval-string

`?fn` in ?file calls `engine.eval(<string literal>)`. Inline string-eval can't be tested independently of the surrounding Rust code and bypasses any script registry. Move the script to a `.rhai` file and load it via `engine.compile_file(...)` (or `compile(...)` on `include_str!`-ed content) so the AST can be cached, values-checked at build time, and exercised in isolation.

engine_eval_string_literal + file_extension_is
blockprerhai

block-rhai-print-in-script

`print(` appears in a .rhai script. `print` is Rhai's equivalent of `dbg!()` — debug output that bypasses whatever response/logging channel your host has registered. Use the host-registered function for emitting output (commonly a `log`, `emit`, or `response_*` proxy your `Engine` exposes via `register_fn`) so script output flows through the same path as the rest of your application.

new_content_contains + file_extension_is

python pack

warnprepython

warn-print-in-src

print() in ?fn (?file) — consider logging.info()/debug() instead. Remove debug prints before committing. Upstream: style guidance, not a correctness rule.

python_print_call + file_path_matches
blockprepython

enforce-no-bare-except

Don't use bare `except:` — catch specific exception types. Bare except swallows KeyboardInterrupt and SystemExit. Upstream: PLE0704 (pylint), Bugbear B001.

python_bare_except
warnprepython

warn-python-mutable-default-arg

Mutable default `?param` in ?fn — defaults are created once at def time and shared across calls. Use None and create inside. Upstream: Bugbear B006.

python_mutable_default_arg
warnauditpython

audit-python-call-in-default-arg

Function call `?callee()` in default argument `?param` of ?fn — evaluated once at def time. If it returns a mutable or side-effectful value, this is a bug. Upstream: Bugbear B008 (narrower: only flags call expressions, not bare mutable literals which are covered by B006).

python_call_in_default_arg
warnprepython

warn-python-swallowed-exception

Handler for ?exception in ?fn is empty (`pass`/`...`/comments) — the exception is silently swallowed. Recommend handling, re-raising, or documenting the intentional fallback. Upstream: Bugbear B110 (narrower: typed handlers only; bare handlers caught by enforce-no-bare-except).

python_exception_handler_passes
warnauditpython

audit-python-high-param-count

Function ?fn in ?file has ?count parameters — consider grouping into a config object or using the builder pattern. Exclude self/cls. Upstream: design smell (maintainability, not correctness).

python_function_param_count_high
warnauditpython

audit-python-missing-docstring

Public def ?fn in ?file has no docstring. Upstream: documentation best practice; audit-only because docstring policy is project-dependent.

python_function_missing_docstring
warnprepython

warn-python-import-time-io

Import-time I/O via `?callee` in ?file makes importing the module expensive and fallible even when callers never use that feature. Defer it until first use unless this is a small packaged-data read.

python_import_time_io
warnprepython

warn-python-is-literal

`?fn` in ?file compares a value literal by identity — use `==`/`!=`. Reserve `is` for None, booleans, Ellipsis, and unique sentinel objects.

python_is_literal_comparison
warnauditpython

audit-python-mutated-module-global

`?fn` in ?file mutates module-level container `?global` — review the resulting cross-call/test coupling and prefer passing state explicitly when practical. This is syntactic evidence and may be a shadowed local.

python_mutated_module_global
warnauditpython

audit-python-star-import

?file uses `from ?module import *`, obscuring dependencies and allowing silent name collisions. Import explicit names; package `__init__.py` re-export surfaces are an intentional exception.

python_star_import

python-patterns pack

warnprepython-patterns

warn-python-global-statement

`?fn` in ?file rebinds module global `?name` with `global`. Shared mutable module state couples callers and tests and cannot be instantiated twice. Move the state onto a class and bind its methods to module names explicitly (Prebound Methods: https://python-patterns.guide/python/prebound-methods/; Global Object: https://python-patterns.guide/python/module-globals/). Heuristic limit: syntax only — a `global` used once for lazy initialization of an immutable value is also flagged.

python_global_statement
warnprepython-patterns

warn-python-globals-introspection-assignment

`?fn` in ?file assigns through `globals()[...]`. Binding module names by introspection hides them from readers, linters, and IDEs; assign each prebound method explicitly (`random = _instance.random`). See https://python-patterns.guide/python/prebound-methods/. Heuristic limit: any `globals()[...] = ...` store is flagged, including deliberate plugin registries.

python_globals_subscript_assignment
warnprepython-patterns

warn-python-dynamic-class-creation

`?fn` in ?file builds a class at runtime with `type(name, bases, ns)`. Generated classes are hard to debug, navigate, and type-check; compose independent objects instead. See https://python-patterns.guide/gang-of-four/composition-over-inheritance/. Heuristic limit: flags every three-argument `type(...)` call, including metaclass-style library code that needs it.

python_dynamic_class_creation
warnprepython-patterns

warn-python-singleton-new

Class `?class` in ?file implements the Singleton Pattern by overriding `__new__` around a cached `_instance`. `?class()` then reads like construction but is not, and tests cannot get a fresh instance. Prefer a module-level instance (The Global Object Pattern): https://python-patterns.guide/gang-of-four/singleton/. Heuristic limit: detection keys on an `_instance`/`_instances`/`_singleton` attribute inside `__new__`.

python_new_override
warnauditpython-patterns

audit-python-custom-new

Class `?class` in ?file overrides `__new__`. If this is a Flyweight cache (`Grade(95)` returning a shared object), the guide prefers a plain factory function whose behaviour matches its spelling: https://python-patterns.guide/gang-of-four/flyweight/. Heuristic limit: `__new__` is also the right tool for immutable subclasses (`int`, `tuple`), which this audit cannot distinguish — review, do not rewrite blindly.

python_new_override
warnauditpython-patterns

audit-python-isinstance-dispatch

`?fn` in ?file dispatches on the same value across ?count `isinstance(...)` branches. Type dispatch in the caller is what the Composite Pattern removes: give every object in the hierarchy the same method (leaf objects return an empty result) so callers treat them symmetrically. See https://python-patterns.guide/gang-of-four/composite/. Heuristic limit: only positive `if`/`elif` chains over non-builtin domain types are counted; framework boundary dispatch and functools.singledispatch fallbacks can still match.

python_isinstance_chain
warnprepython-patterns

warn-python-container-is-own-iterator

Container class `?class` in ?file returns `self` from `__iter__` and implements `__next__`, so only one traversal can be in flight at a time (nested `for` loops over the same object break). Return a separate iterator object or write `__iter__` as a generator. See https://python-patterns.guide/gang-of-four/iterator/. Heuristic limit: 'container' means the class also defines `__len__`, `__getitem__`, or `__contains__`; file-like stream objects that intentionally share state are not excluded.

python_container_is_own_iterator
warnprepython-patterns

warn-python-multiple-inheritance

Class `?class` in ?file inherits from ?count concrete classes. Combining features by multiple inheritance is order-dependent, risks attribute collisions, and needs m×n combination tests; compose the pieces as attributes instead. See https://python-patterns.guide/gang-of-four/composition-over-inheritance/. Heuristic limit: bases named `*Mixin`/`*ABC`, `Protocol`, `Generic`, `NamedTuple`, `TypedDict`, `Enum`, and `metaclass=` are not counted; other abstract bases are.

python_multiple_inheritance
warnauditpython-patterns

audit-python-deep-inheritance

Class `?class` in ?file sits ?depth levels deep in an inheritance chain defined in this file. Deep hierarchies are the 'subclass explosion' the guide warns about; prefer composing small independent classes. See https://python-patterns.guide/gang-of-four/composition-over-inheritance/. Heuristic limit: depth is computed from classes in the same file only, so it understates real depth and says nothing about framework base classes.

python_inheritance_depth
warnprepython-patterns

warn-python-mixin-with-init

Mixin `?class` in ?file defines `__init__`. A mixin with its own constructor makes cooperative `super().__init__` chains order-dependent and fragile; give the mixin class attributes with defaults, or compose the behaviour as a separate object. See https://python-patterns.guide/gang-of-four/composition-over-inheritance/. Heuristic limit: a mixin is recognised by the `Mixin` name suffix only.

python_mixin_with_init
warnprepython-patterns

warn-python-static-delegation-wrapper

Class `?class` in ?file re-declares ?count methods that only forward to `self.?attr`. This static Decorator-pattern wrapper must be maintained whenever the wrapped class changes and silently misses methods it never listed. Prefer a dynamic wrapper: `def __getattr__(self, name): return getattr(self.?attr, name)`, overriding only the methods you change. See https://python-patterns.guide/gang-of-four/decorator-pattern/. Heuristic limit: counts single-statement `return self.?attr.<same name>(...)` methods; an adapter that renames methods is not detected.

python_static_delegation_wrapper
warnprepython-patterns

warn-python-mutable-class-attribute

Class `?class` in ?file assigns mutable container `?attr` in the class body, so every instance shares one object — the same coupling hazard as a mutable module global. Create it in `__init__` (or use a dataclass `field(default_factory=...)`) unless it is a deliberate class-wide registry. See https://python-patterns.guide/python/module-globals/. Heuristic limit: dunder names are skipped; intentional class-level caches are still flagged.

python_mutable_class_attribute
warnprepython-patterns

warn-python-equality-with-none

`?fn` in ?file compares against `None` with `==`/`!=`. `None` is a sentinel and must be tested by identity (`is None` / `is not None`); `==` dispatches to `__eq__`, which NumPy arrays, ORMs, and mocks override. See https://python-patterns.guide/python/sentinel-object/. Upstream: pycodestyle E711.

python_equality_with_none

typescript pack

warnpretypescript

warn-console-log-in-src

console.log in src/ — remove before committing, or use a proper logger.

ts_console_log_call + file_path_matches
warnpretypescript

warn-ts-explicit-any-ast

?count explicit `any` annotation(s) in ?fn (?file) — narrow the type, or use `unknown` and refine with type guards.

ts_explicit_any
warnpretypescript

warn-ts-suppression-comment

?count @ts-ignore/@ts-expect-error/@ts-nocheck comment(s) in ?file — each one turns the type checker off somewhere. Fix the type instead.

ts_suppression_comment
warnaudittypescript

audit-ts-non-null-assertion

?count non-null assertion(s) (`x!`) in ?fn (?file) — prefer explicit narrowing or optional chaining.

ts_non_null_assertion
warnposttypescript

warn-ts-function-param-count-high

Function `?fn` in ?file has ?count parameters. Consider grouping related params into an options object or splitting the function — long signatures correlate with God-function debt.

ts_function_param_count_high

swift pack

warnpostswift

warn-swift-force-unwrap

Function `?fn` in ?file uses ?count force-unwrap(s). Prefer guard let or if let; reserve ! for invariants you can document.

function_uses_force_unwrap
warnpostswift

warn-swift-throws-with-force-unwrap

`?fn` in ?file is declared `throws` yet force-unwraps ?count time(s). Since the function can already propagate failure, replace the `!` with `guard let ... else { throw ... }` so callers get an error instead of a crash.

function_throws + function_uses_force_unwrap
warnpreswift

warn-swift-try-bang

try! crashes on error — prefer try with do/catch, or try? when an Optional result is acceptable.

swift_governed_construct + file_extension_is
warnpreswift

warn-swift-force-cast

Force-cast `as!` crashes on type mismatch — prefer `as?` with `if let`/`guard let`. Completes the force-bang trio with `!` and `try!`.

swift_governed_construct + file_extension_is
warnauditswift

audit-swift-fatal-error

`fatalError(` aborts the process — for recoverable conditions prefer a `throws` API and let the caller decide. Reserve `fatalError` for genuinely unreachable invariants (and prefer `precondition`/`assertionFailure` when the intent is a debug-only trap).

swift_governed_construct + file_extension_is
warnauditswift

audit-swift-mutable-singleton

`static var shared` is a mutable global — the Singleton pattern (eleev/swift-design-patterns §Creational/Singleton) uses `static let shared` so the instance can't be swapped at runtime. If mutability is intentional, add a comment or move state inside the instance.

swift_governed_construct + file_extension_is
warnauditswift

audit-swift-legacy-constructor

Legacy C-style constructor — prefer the modern Swift initializer (e.g. `CGRect(x:y:width:height:)`, `UIEdgeInsets(top:left:bottom:right:)`). Mirrors SwiftLint's `legacy_constructor` rule.

swift_governed_construct + file_extension_is
warnauditswift

audit-swift-legacy-random

Legacy random API — Swift 4.2+ ships `Int.random(in:)`, `Double.random(in:)`, and `Collection.randomElement()`, which work on all platforms (not just Darwin) and are uniformly distributed without modulo bias. Mirrors SwiftLint's `legacy_random` rule.

swift_governed_construct + file_extension_is

confidence pack

warnpreconfidence

confidence-low-blocks-commit

Low confidence — compile/tests/known-bug evidence is incomplete or failing. Run `phr-mcp confidence` for the per-signal report before presenting this as done.

bash_command_matches + __script__
warnpreconfidence

confidence-medium-warns-commit

Medium confidence — one grounded signal is missing. Review before presenting this as done.

bash_command_matches + __script__

structural pack

warnprestructural

warn-untested-risky-call

`?func` (in ?file) calls a panicking API from the unwrap/expect/panic/todo/unimplemented family, and no test calls it directly. A panicking path with no test is where a crash reaches a user unnoticed — add a test that exercises this function, or handle the failure case explicitly. Coverage is matched by direct call only, so a function covered transitively may still be flagged.

edited_file + file_type + defines_fn + (calls_api | calls_api | calls_api | calls_api | calls_api) + no_direct_test
warnprestructural

warn-import-cycle

Module `?module` is part of import cycle `?cycle`. Mutually importing modules can't be understood, tested, or extracted independently, and the cycle tends to attract more coupling over time. Move the shared items into a third module both can depend on.

edited_file + declares_module + in_cycle
warnprestructural

warn-ts-untested-risky-call

`?func` uses a non-null assertion (`!`) and has no direct test. `!` tells the compiler a value cannot be null and produces no runtime check, so when the assumption is wrong the failure surfaces later and elsewhere, usually as a TypeError. Add a test that exercises the null case, or narrow the type so the assertion is unnecessary.

edited_file + file_type + defines_fn + calls_api + no_direct_test
warnprestructural

warn-unconsumed-config-key

Generated configuration key `?pointer` in ?artifact has no accepted field on ?consumer and may be silently dropped. Rename or alias the field, remove the key, or make intentional extra-field handling explicit.

edited_file + declares_module + unconsumed_data_key
warnprestructural

warn-generated-artifact-diagnostic

Generated-artifact binding has diagnostic `?kind` for `?reference`; no cross-language seam was guessed. Correct the exact producer, artifact, or consumer reference.

edited_file + generated_artifact_diagnostic

lua pack

warnprelua

warn-lua-dynamic-code-load

Dynamic code load (`?loader`) in Lua module `?module` — dynamic code loading bypasses static analysis and may execute untrusted code. Prefer pre-loaded modules via `require`.

lua_dynamic_code_load + file_extension_is

cue pack

warnprecue

warn-cue-import-diagnostic

CUE import `?import` in ?file is `?kind`; no repository-local dependency edge was guessed. Add a package qualifier or correct the module/package path.

edited_file + cue_import_diagnostic

json pack

warnauditjson

audit-json-schema-unknown-dialect

JSON Schema file ?file declares `$schema` as `?$dialect` which is not a supported dialect. Only recognized dialects receive schema resolution support — check the `$schema` value or file is not a JSON Schema.

json_schema_unknown_dialect

yaml pack

warnpreyaml

block-yaml-duplicate-key

Duplicate key `?key` at line ?line in ?file — YAML consumers may silently choose one value or reject the document. Merge the conflicting keys into a single entry.

yaml_duplicate_key
warnpreyaml

block-yaml-invalid-alias

YAML alias `?alias` in module ?module (?file) is undefined — the anchor has not been defined earlier in this document. Define the anchor before using it.

yaml_undefined_alias
warnpostyaml

warn-yaml-legacy-merge-key

Legacy merge key `<<` at line ?line in ?file — the YAML merge key is a legacy feature from YAML 1.1 that can produce unexpected results with complex mappings. Consider using explicit key duplication or a dedicated configuration format.

yaml_merge_key

helm3 pack

warnaudithelm3

audit-helm3-tpl

Dynamic template evaluation `?tpl_call` in ?file — the template name is computed at render time, so the static graph cannot determine which template will be invoked. Verify the dynamic call resolves correctly at render time.

helm3_dynamic_tpl
warnaudithelm3

audit-helm3-lookup

Helm template in ?file uses `lookup` — render depends on live cluster state and cannot be fully validated offline. Use `helm template --dry-run` with a test cluster to verify behavior.

helm3_cluster_lookup