Skip to content

Build Diagnostics

Some compliance rules are checked by the build itself. When one fires, you get a diagnostic id — look it up here for what the build wants and how to satisfy it.

Build diagnostics cover only the technical requirements, the ones that protect the platform. Behavior checks, which describe how a device appears in PQ, are never enforced by the build.

These checks are a floor, not the whole rule. A clean build means the mechanical violations are absent; the rule's judgement still applies to everything a compiler cannot see.

PQA — the declared model

Reported while the YAML is read, before any code is generated. These are defects in what the adapter declares: its device tree, its access model, its events.

Id Rule What it reports
PQA001 Adapter configuration must be reachable No adapter registration is visible to the generator
PQA002 Adapter configuration must parse The registration is malformed, or declares a rejected value
PQA003 Identity fields are required adapter_id, name, version, adapter_type, or a TCP frame_type is missing
PQA004 Functions must exist A device type declares a function that is neither a framework nor a custom function
PQA005 Generated entry point is skipped An executable project already declares Main
PQA006 Function catalogue must be reachable functions.yaml is in neither the additional files nor the framework assembly
PQA007 Event ids carry the pq.event. prefix A declared event id is missing the prefix
PQA008 Custom function overrides system function A custom function shadows a framework function of the same name
PQA009 Command ids carry the pq.command. prefix A declared command id is missing the prefix
PQA010 Commands configuration must parse pq-commands.yaml is malformed or empty
PQA012 Model references must be acyclic Access-model entities reference each other in a cycle
PQA013 Allocated addresses need a range address: uint without range: [min, max]
PQA014 Device types declare a category A non-derived device type has no category
PQA015 One addressing strategy per entity An entity declares both id and address
PQA016 Natural key must name a property id: names a property the entity does not declare
PQA017 Inheritance must be acyclic Device types form a cycle through extends:
PQA018 Base device type must exist extends: names a type this adapter does not declare
PQA019 Abstract functions are not usable directly A device type declares an abstract function
PQA021 Update mode must be known updatable: is neither inplace nor replace
PQA022 Range requires an allocated address range on an address that is not uint
PQA023 Tracked addresses are uint A tracked entity uses another numeric address type
PQA024 Identity must name a property identity: names a property the type does not have
PQA025 Identity needs a resolvable parent An identity-declaring type sits under a passthrough parent
PQA026 Type identity requires a singleton identity: type without max_siblings: 1 on a parent
PQA027 Events must exist in the taxonomy A declared event id is not in pq-events.yaml
PQA028 Owner must be known owner: is neither person nor shared
PQA029 Natural-id entities have no owner An entity keyed by id: declares owner:
PQA030 One person-owned root The access model infers more than one root
PQA031 Parent references must exist parents: names a type this adapter does not declare
PQA032 Property types must resolve A property type: matches no primitive, device type, or public enum

Ids are allocated once and never reused; PQA011 and PQA020 are unassigned, so the sequence skips them.

PQC — the written code

Reported from the adapter's C# code. These are defects in how the declared model is implemented.

Id Rule What it reports
PQC152 Time sync capability and implementation must agree capabilities.time_sync is set without ITimeSynchronized, or the reverse
PQC203 Events must be declared in YAML, not built by hand Adapter code builds an event with EventBuilder.Event(...) or a PqEvent.* builder
PQC201 Status poll must not participate in event processing A poll publishes events without declaring the exception, or touches the replay cursor
PQC209 Initial state must use a snapshot, not events A device event is published from OnConnected while reading initial state
PQC211 Command handlers publish from the confirming event A handler publishes a device event directly instead of from the ExecuteCommand callback
PQC213 Blanket ignore hides unresolved device addresses A route ignores every event of a type that is also routed by address
PQC251 Poll must cover every status function it can A status function the Thing declares is never set by the poll
PQC232 Event publication must be encapsulated in the owning Thing A class publishes an event through a reference to a Thing it does not own
PQC257 Set the device clock from the wall clock, never a re-projected local time GetLocalNow().LocalDateTime re-projects the device wall clock onto the host process zone
PQC302 Follow-up factory must be pure A followUpFactory callback does something other than build the trailing frame

Other generator diagnostics

Reported by the generator's command and enrollment checks. They keep their own id bands.

Id Rule What it reports
PQ0001 Declared commands need a handler A commands: entry has no handler in the code
PQ0002 Handlers need a declared command A handler handles a command no device type declares
TD001 Template classes are partial [BinarySerializedBlob] / [BiometricTemplate] class is not partial
TD002 Template classes serialize something The class has no public byte[], byte[][] or primitive property with a setter
TD003 Biometric templates have no required properties A [BiometricTemplate] class declares a required property

Severity

Most PQA diagnostics are errors from the start: a model that contradicts itself has no correct interpretation to fall back on, so generating from it produces code that misbehaves rather than code that fails.

PQC diagnostics arrive as warnings while adapters are brought into line, then become errors. Treat a warning as a defect with a deadline, not as advice.

Suppression

Do not suppress a compliance diagnostic. If you believe a report is wrong, it is a bug in the check — say so, with the code that triggered it. Every rule here exists because the failure it prevents reached a customer at least once.