Skip to content

Definition Of Done

Use this checklist to decide whether an adapter implementation or major adapter update is complete.

Two kinds of checks

Technical requirements protect the platform: memory safety, stable long-running operation and correct use of the framework (for example, no direct EventBuilder calls). Protequ requires them. The build enforces many of them with analyzers; review checks the rest.

Behavior checks describe how a device appears in PQ (for example, a detector alarm also raises its partition). We recommend that your adapter meets all of them. If you decide not to, for any reason, that is a legitimate choice and it is yours. How closely an adapter matches PQ behavior can only influence a customer's decision whether to install it.

Each gate below carries a Verified by line naming the registries that check it: compliance rules (RULE-/COMM-) in compliance-rules.md, structural conventions (MODEL-) in modeling-conventions.md, behavioural scenarios (AAT-) in acceptance-tests, and build diagnostics (PQA/PQC) in diagnostics. A gate item with no id is judged by review alone.

Your inputs are only the protocol/vendor documentation and this docs/adapter-development documentation set. The output must be the maximum feature set supported by both the protocol and the current framework.

Completion Rule

An adapter is done only when every discovered protocol capability has one of these final states:

  • implemented
  • not supported by protocol
  • not supported by framework
  • blocked by missing or ambiguous documentation
  • blocked by hardware-only verification
  • intentionally deferred by explicit user scope

Do not mark an adapter done because one vertical slice works. A vertical slice proves the architecture; it does not prove feature coverage.

Scoped Work Rule

For bug fixes and explicitly scoped feature extensions, do not expand implementation to unrelated protocol areas.

The changed capability still must satisfy the relevant gates in this document. Update the capability matrix, local documentation, and checklist only for affected capabilities, and preserve existing backlog/final states for unrelated areas.

For new adapters and major rewrites, the full maximum feature set rule applies.

Required Evidence

  • selected archetype from archetypes/
  • capability matrix with every capability marked by final state
  • Thing hierarchy table
  • command mapping table
  • event/status mapping table
  • access/enrollment/APB mapping when the protocol supports stored credentials, biometrics, readers, doors, zones, or entry/exit state
  • unknowns/evidence table when any protocol area is incomplete, ambiguous, or undocumented
  • adapter-local notes that let another developer continue without rediscovering architecture or protocol rules
  • verification summary with performed checks and remaining hardware-only gaps

Protocol Coverage Gate

  • all documented hardware object types are reviewed and either represented as Things or explicitly excluded with evidence
  • all documented protocol commands/actions are reviewed and either implemented, mapped to an existing framework command, or explicitly excluded with evidence
  • all documented event categories, status records, alarms, troubles, and restore events are reviewed
  • all documented credential, schedule, user, access level, holiday, biometric, card format, PIN, APB, time, I/O, intrusion, video, and enrollment capabilities are reviewed when present in the protocol
  • all protocol constants, event codes, command numbers, enum values, bitmasks, frame fields, and magic values are traceable to vendor documentation or provided source material
  • undocumented values are recorded as unknowns; they are not guessed from neighboring values or naming patterns
  • unknown values may appear in analysis or backlog documentation, but not as implemented protocol constants unless the user explicitly supplies authoritative evidence

Verified by: RULE-004 (constants traceable to vendor documentation), RULE-020 and RULE-027 (every device event reviewed and classified), RULE-024 (each vendor stream keeps its own semantics).

Framework Coverage Gate

  • each protocol capability is mapped to the strongest current framework concept: Thing, function, command, event, status, polling, access sync, APB sync, enrollment, time sync, stream handling, or custom function
  • unsupported framework gaps are documented as not supported by framework, not silently omitted
  • capabilities-coverage.yaml exists at the adapter root and declares every integration capability from reference/capability-catalog.md with a final state and evidence, per reference/capabilities-coverage.md
  • generated framework patterns are used instead of manual plumbing when available
  • Things remain minimal and do not duplicate generated function state
  • no long-lived service, timer, callback, or closure keeps direct Thing references across async boundaries

Verified by: RULE-002 (no Thing references across async), RULE-019 (no empty partial for generated Things), RULE-036 (framework-bending smell).

YAML Gate

  • adapter-registration.yaml exists and defines adapter identity, security domains, capabilities, transport, protocol address/event/frame types, Thing types, functions, commands, properties, parents, and limits
  • adapter-registration.yaml validates against reference/adapter-registration.schema.json
  • access-model.yaml validates against reference/access-model.schema.json when present
  • YAML uses schema-defined block names and property names; custom structure is not invented to work around missing framework support
  • adapter_id is globally unique in the repository
  • secrets and keys are marked sensitive: true; private/internal configuration is marked private: true when appropriate
  • address ranges, natural keys, parent constraints, max siblings, and categories match protocol hardware limits
  • YAML-declared commands/functions/events match implemented handlers and generated usage
  • access-model.yaml and apb-model.yaml exist when the protocol supports local credential storage or antipassback state

Verified by: MODEL-001 to MODEL-016 (structural shape of the declared tree), RULE-049 (closed-set properties are enums), and the PQA build diagnostics, which reject a contradictory declaration at compile time — PQA004, PQA012 to PQA032.

Implementation Gate

  • connection lifecycle is implemented and documented: connect, authenticate, initialize, bind/register, start polling or event stream, graceful disconnect, reconnect
  • heartbeat/watchdog/status behavior is implemented when the protocol exposes liveness or requires keepalive
  • event replay, event deduplication, event loss, or lack of offline recovery is explicitly handled and documented
  • command handlers cover all implemented command mappings and report failure/timeout accurately
  • command-originated state changes are confirmed by device response or documented as ACK-only behavior
  • event routing covers every supported vendor event and preserves unresolved-address diagnostics
  • ignored or suppressed protocol events are intentional, documented, and do not pollute audit as unknown security events
  • unhandled relevant events are logged or published as unknown/unresolved; they are not silently dropped
  • status polling uses framework polling patterns when device state is not pushed as events
  • time synchronization is implemented when the device has a writable or readable clock
  • vendor-specific limitations and quirks are documented locally

Verified by: RULE-017 and RULE-018 (connection and shared-resource lifecycle), RULE-058 (authentication verdict comes from the device), RULE-052 and RULE-057 with diagnostics PQC152 and PQC257 (time synchronization), RULE-007, RULE-011 and RULE-038 with diagnostic PQC211 (commands), RULE-003, RULE-008, RULE-009, RULE-012, RULE-013, RULE-025, RULE-032 and RULE-054 with diagnostics PQC203, PQC209, PQC213 and PQC232 (event routing, replay and audit sourcing), RULE-020, RULE-024, RULE-026, RULE-027 and RULE-060 (nothing audit-relevant is dropped), RULE-001, RULE-010, RULE-050 and RULE-051 with diagnostics PQC201 and PQC251 (status and history polling), COMM-001 to COMM-011 with diagnostic PQC302 (protocol channel behaviour), RULE-005 (unknown addresses stay diagnosable).

Access Synchronization Gate

Apply when the protocol stores users, credentials, schedules, groups, access levels, biometric templates, PINs, or card formats.

  • access-model.yaml defines all supported device-side entities in dependency order
  • Transform() rejects invalid input by returning null or excluding the entity, not by throwing for normal unsupported data
  • tracked-entity Address is owned by the framework: do not call SetAddress() and do not read entity.Address for model references
  • stable natural keys are used where the protocol requires them
  • credential filtering rules are explicit: unsupported card/PIN/biometric formats are documented
  • first sync, reset sync, deletion, and device cleanup semantics are documented
  • unchanged double-sync is verified: running sync twice with unchanged input does not throw and does not create duplicate device state

Verified by: RULE-006 (Transform does not throw), RULE-014 (idempotent sync), RULE-039 (best-effort batch), RULE-016 and RULE-040 (entity-typed cross-references), RULE-037 (generated typed person input), RULE-035 (holidays are not stubs), RULE-056 (ownership drives identity resolution), RULE-015, RULE-021, RULE-022, RULE-041, RULE-055 and RULE-059 (credential projection and record shape). Behaviour: AAT-ACCESS-DOUBLE-SYNC, AAT-ACCESS-SYNC-MODE, AAT-ACCESS-SYNC-ISOLATION, AAT-ACCESS-OWNERSHIP, AAT-ACCESS-CASCADE, AAT-ACCESS-CREDENTIAL, AAT-ACCESS-CARD-FORMATS, AAT-ACCESS-SCHEDULES, AAT-ACCESS-HOLIDAYS, AAT-ACCESS-ACCESS-LEVELS, AAT-ACCESS-RESET-RESTORE.

Capability-Specific Gates

Every integration capability listed in reference/capability-catalog.md for each in-scope domain (cross-cutting, access, intrusion, video, I/O, gateway/native-SDK) must be evaluated and carry a final state. The catalog is the single source of the expected-capability lists; it also backs the directed survey pass and the capability matrix, so the same set is used to scope, build, and verify.

Verification Gate

  • adapter project build passes; do not require a full solution build
  • generated code shape is checked after YAML, source-generator, command, event, polling, access sync, or APB changes
  • one connection path is verified or marked hardware-blocked
  • one command path is verified or marked hardware-blocked
  • one event or status path is verified or marked hardware-blocked
  • access sync double-sync is verified when access sync is applicable
  • hardware-only tests are listed with exact prerequisites and current status
  • adapter review is performed against framework patterns, or the reason for skipping it is documented

Verified by: the acceptance-test matrix — AAT-CROSS-CUTTING-UNIVERSAL (connection, startup, restart), AAT-CROSS-CUTTING-COMMAND-TARGETING (a command reaches the addressed Thing and no other), AAT-CROSS-CUTTING-SUPERVISION, AAT-CROSS-CUTTING-DISCOVERY, AAT-CROSS-CUTTING-TIME-SYNC, AAT-ACCESS-DOUBLE-SYNC — plus the full walk of compliance-rules.md for the review itself.

Published Documentation Gate

The adapter's published reference pages are rendered from its own declarations by Pq.Tools.AdapterDocs; the files below are the input, and a missing one leaves a hole in the published documentation:

  • capabilities-coverage.yaml exists at the adapter root, per the Framework Coverage Gate
  • every capability whose state is not implemented carries a limitation — one sentence in plain language saying what the user does not get, with no protocol or framework names, per reference/capabilities-coverage.md
  • device type and property descriptions are written for the installer who reads the published page — what the thing is and what the setting does, with no command numbers, frame fields or protocol enumeration values, per reference/yaml-properties.md; protocol documentation is not required in YAML
  • pq-tools docs --bundle /work --preview /work/preview renders without error — the published pages are generated from these inputs at publish time, not committed, so the inputs above are what must be correct; the complete authoring loop is in Writing and delivering adapter documentation
  • docs/connection.md exists and follows the skeleton in reference/connection-guide.md — how to physically connect the hardware to Protequ cannot be derived from YAML, and an installer needs it on the panel; even a trivial IP panel states that there is nothing to set on the box
  • narrative the structured pages do not cover — gotchas, site-specific advice, quirks — lives in the adapter's optional docs/notes.md when it is worth publishing
  • for an adapter delivered by a third party, the handover folder carries these files, per documentation-deliverable.md

Local Documentation Gate

Adapter-local documentation must include:

  • architecture and Thing tree
  • protocol or SDK source references
  • connection sequence and reconnect behavior
  • command table
  • event/status table
  • polling behavior
  • access/enrollment/APB model when applicable
  • configuration properties and sensitive fields
  • known quirks, protocol traps, unsupported capabilities, and backlog
  • build command for the adapter project

Verified by: RULE-023 (documentation must not drift from code), RULE-004 (every protocol constant carries its citation).

Failure Conditions

The adapter is not done if any of these are true:

  • a protocol feature is unreviewed
  • a protocol constant is invented or undocumented without being marked unknown
  • a capability is omitted without final state and evidence
  • capabilities-coverage.yaml is missing, so the published pages cannot state what the adapter supports
  • docs/connection.md is missing, so an installer has no documented way to get the hardware talking to Protequ
  • event-dispositions.yaml still carries a gap — an event the device can report that the adapter does not translate is unfinished work, not a documented characteristic
  • events can be silently dropped without documentation
  • the adapter relies on manual framework plumbing where generated patterns exist
  • access sync can create duplicate state on unchanged repeated sync
  • local documentation is stale enough that another developer cannot safely continue