PQA025 — Identity scope broken by passthrough parent¶
A type that declares identity sits under a parent that has neither identity nor the ability to be a root.
An identity key is unique within its parent, not globally: input 1 under module 3 is a different device from input 1 under module 7. The reconciler therefore needs to identify the parent before it can re-pair the child, which requires the parent to be identifiable — it declares its own identity:, or it is root-capable (declares no parents:) and is therefore reachable without one.
A parent that is neither is a passthrough sitting in the middle of the chain: it is re-created on every discovery, and there is no way to say which one of them the child belongs to.
- type_id: Bus # no identity, and not root-capable
parents:
Panel:
- type_id: Input
identity: [port] # scoped to a parent nobody can name
parents:
Bus:
Why the build refuses this¶
The scope silently collapses. Without a resolvable parent, identity port: 1 matches every input on every bus. Re-pairing then either attaches devices to the wrong parent or imports the whole subtree again.
How to fix it¶
Give the intervening type an identity. A bus has a number, a port has an index — whatever the protocol uses to tell two of them apart. If the type is genuinely a singleton under its parent, identity: type says exactly that (see PQA026).
Or remove the intervening level. A passthrough type that carries no hardware distinction is often modelling noise; attaching the child directly to the identifiable ancestor makes the scope explicit.
What is not reported¶
A root-capable parent. A type with no parents: block anchors the chain by itself.
A parent whose identity comes from extends:. Identity inherited through the chain counts as declared.
If you disagree with a report¶
Do not suppress it. A wrong report is a bug in the check — report it with the YAML that triggered it.