From 70b0fb8eca7cf5a080f62bdd52e8f68b0c8c27f9 Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 20 May 2026 23:10:12 -0700 Subject: [PATCH 1/6] test(conformance): add golden CALL frame for bool and string payload Add a golden-frame conformance case for a CALL frame whose CBOR body contains an explicit boolean and a short string. This pins non-numeric scalar encoding byte-for-byte using the `set_enabled` intent with `{enabled: true, label: "ok"}` so ports can verify canonical CBOR output against the corpus. Co-Authored-By: OpenAI GPT-5.4 --- tests/conformance/golden_frames.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/conformance/golden_frames.yaml b/tests/conformance/golden_frames.yaml index 3539bee..548fbca 100644 --- a/tests/conformance/golden_frames.yaml +++ b/tests/conformance/golden_frames.yaml @@ -66,6 +66,15 @@ b: 0 cbor_hex: "a3 61 72 18 ff 61 67 18 64 61 62 00" +- name: call with explicit bool + string payload + kind: 0x01 + seq: 6 + intent: "set_enabled" + payload: + enabled: true + label: ok + cbor_hex: "a2 67 65 6e 61 62 6c 65 64 f5 65 6c 61 62 65 6c 62 6f 6b" + - name: reply with bool kind: 0x02 seq: 5 From 23f42303983bbc129b7c5adc4241f4073bf1141c Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 20 May 2026 23:18:30 -0700 Subject: [PATCH 2/6] test(conformance): add golden REPLY frame for explicit empty map Add a golden-frame conformance case for a REPLY frame whose payload is encoded as an explicit CBOR empty map. This complements the existing empty CALL coverage using a reply with `payload: {}` and `cbor_hex: "a0"` so ports verify that explicit empty reply bodies decode the same way. Co-Authored-By: OpenAI GPT-5.4 --- tests/conformance/golden_frames.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/conformance/golden_frames.yaml b/tests/conformance/golden_frames.yaml index 548fbca..7f9563d 100644 --- a/tests/conformance/golden_frames.yaml +++ b/tests/conformance/golden_frames.yaml @@ -32,6 +32,13 @@ value: 0.0 cbor_hex: "a1 65 76 61 6c 75 65 fb 00 00 00 00 00 00 00 00" +- name: "reply with empty-map body" + kind: 0x02 + seq: 8 + intent: "ping" + payload: {} + cbor_hex: "a0" + - name: dry-run call with one float kind: 0x81 seq: 99 From adcf93bd7762536098da4832ca01e5fc7e87aba3 Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 20 May 2026 23:28:54 -0700 Subject: [PATCH 3/6] test(conformance): add multi-field ERROR golden frame Add a golden-frame conformance case for an ERROR frame whose CBOR body carries multiple fields. This extends the current single-field error coverage using the `unknown` intent with `{status: 4, message: "unknown", code: 404}` so ports must preserve the full error map. Co-Authored-By: OpenAI GPT-5.4 --- tests/conformance/golden_frames.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/conformance/golden_frames.yaml b/tests/conformance/golden_frames.yaml index 7f9563d..e6225f0 100644 --- a/tests/conformance/golden_frames.yaml +++ b/tests/conformance/golden_frames.yaml @@ -32,7 +32,7 @@ value: 0.0 cbor_hex: "a1 65 76 61 6c 75 65 fb 00 00 00 00 00 00 00 00" -- name: "reply with empty-map body" +- name: reply with empty-map body kind: 0x02 seq: 8 intent: "ping" @@ -55,6 +55,16 @@ status: 4 cbor_hex: "a1 66 73 74 61 74 75 73 04" +- name: error with multi-field payload + kind: 0x04 + seq: 13 + intent: "unknown" + payload: + status: 4 + message: unknown + code: 404 + cbor_hex: "a3 66 73 74 61 74 75 73 04 67 6d 65 73 73 61 67 65 67 75 6e 6b 6e 6f 77 6e 64 63 6f 64 65 19 01 94" + - name: event with float payload kind: 0x03 seq: 0 From a3c654e43f8ced6052dd59cd1b30b8d4a27832ca Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 20 May 2026 23:36:57 -0700 Subject: [PATCH 4/6] test(conformance): add EVENT golden frame for integer boundaries Add a golden-frame conformance case for an EVENT frame whose CBOR body contains unsigned integer boundary values. This pins canonical integer encoding byte-for-byte using the `motion_detected` intent with `{min: 0, max: 255}` so ports verify both single-byte and one-byte-argument unsigned forms. Co-Authored-By: OpenAI GPT-5.4 --- tests/conformance/golden_frames.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/conformance/golden_frames.yaml b/tests/conformance/golden_frames.yaml index e6225f0..c3d7a3c 100644 --- a/tests/conformance/golden_frames.yaml +++ b/tests/conformance/golden_frames.yaml @@ -73,6 +73,15 @@ confidence: 1.0 cbor_hex: "a1 6a 63 6f 6e 66 69 64 65 6e 63 65 fb 3f f0 00 00 00 00 00 00" +- name: event with integer payload at boundaries + kind: 0x03 + seq: 0 + intent: "motion_detected" + payload: + min: 0 + max: 255 + cbor_hex: "a2 63 6d 69 6e 00 63 6d 61 78 18 ff" + - name: call with three small ints kind: 0x01 seq: 0x1234 From 0b4a13615e4d3c4ef8bd792b4f26d1f5bbd2a36d Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 20 May 2026 23:43:10 -0700 Subject: [PATCH 5/6] test(conformance): add golden CALL frame for mixed-width sequence Add a golden-frame conformance case for a CALL frame whose sequence number uses mixed high and low bytes. This exercises big-endian sequence encoding using `seq: 0xff01` with the `set_color` intent and `{r: 255, g: 100, b: 0}` so ports cannot accidentally treat sequence bytes as little-endian. Co-Authored-By: OpenAI GPT-5.4 --- tests/conformance/golden_frames.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/conformance/golden_frames.yaml b/tests/conformance/golden_frames.yaml index c3d7a3c..15a7a85 100644 --- a/tests/conformance/golden_frames.yaml +++ b/tests/conformance/golden_frames.yaml @@ -92,6 +92,16 @@ b: 0 cbor_hex: "a3 61 72 18 ff 61 67 18 64 61 62 00" +- name: call with mixed-width sequence number + kind: 0x01 + seq: 0xff01 + intent: "set_color" + payload: + r: 255 + g: 100 + b: 0 + cbor_hex: "a3 61 72 18 ff 61 67 18 64 61 62 00" + - name: call with explicit bool + string payload kind: 0x01 seq: 6 From 0899e35fcb8375eca112e3d211dda34b152bb38a Mon Sep 17 00:00:00 2001 From: Alex Buckley Date: Wed, 20 May 2026 23:56:17 -0700 Subject: [PATCH 6/6] test(conformance): assert UART wire bytes and frame CRC Extend the golden-frame conformance corpus so the optional `uart_wire_hex` and `crc16` fields are exercised by a real fixture instead of documented-only contract text. Populate both fields on `call with three small ints`, then update the reference conformance runner to assert them when present. This pins the full frame CRC as well as the COBS-wrapped UART bytes emitted by `wrap(...)`, giving ports a concrete byte-for-byte target for framing behavior in addition to the existing header and CBOR-body checks. Also sync the conformance README to the current `cbor_hex` schema and clarify that `uart_wire_hex` represents wrapped frame+CRC bytes without the trailing delimiter byte. Co-Authored-By: OpenAI GPT-5.4 --- tests/conformance/README.md | 20 ++++++++++++-------- tests/conformance/golden_frames.yaml | 2 ++ tests/conformance/test_conformance.py | 8 ++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/conformance/README.md b/tests/conformance/README.md index eca5c22..753f45d 100644 --- a/tests/conformance/README.md +++ b/tests/conformance/README.md @@ -4,11 +4,13 @@ A language-neutral set of golden-frame tests. Any DCP implementation should be able to load `golden_frames.yaml` and verify that: 1. **Encode**: building a frame with the given fields produces the listed - `wire_hex`. -2. **Decode**: parsing the `wire_hex` reproduces the listed fields. + header plus `cbor_hex`. +2. **Decode**: parsing the frame bytes derived from the header and `cbor_hex` + reproduces the listed fields. 3. **Framing**: when `uart_wire_hex` is present, COBS+CRC encoding of the frame produces those bytes; decoding them recovers the frame. -4. **CRC**: `crc16` is the CRC-16/CCITT of the named bytes. +4. **CRC**: when `crc16` is present, it is the CRC-16/CCITT of the frame + bytes before UART wrapping. The Python reference test runner is in `test_conformance.py` and can serve as a template for ports. @@ -22,9 +24,9 @@ as a template for ports. intent: "set_brightness" # required: source string for the intent_id payload: # required: CBOR map contents level: 50.0 - wire_hex: "01 01 ..." # required: full DCP frame (header + cbor) - uart_wire_hex: "0a 01 ..." # optional: COBS-wrapped on-the-wire bytes (no trailing 0x00) - crc16: 0x29b1 # optional: CRC-16 of wire_hex bytes + cbor_hex: "a1 65 ..." # required: CBOR body bytes only + uart_wire_hex: "0a 01 ..." # optional: COBS-wrapped frame+CRC, no trailing 0x00 + crc16: 0x29b1 # optional: CRC-16 of full frame bytes ``` Whitespace in hex is allowed and ignored. Hex is lowercase. @@ -32,8 +34,10 @@ Whitespace in hex is allowed and ignored. Hex is lowercase. ## Adding a new test 1. Pick a single concrete frame shape (call, reply, event, dry-run, error). -2. Compute `wire_hex` from a known-good implementation. -3. Where the spec is silent, prefer the simplest possible CBOR encoding (no +2. Compute `cbor_hex` from a known-good implementation. +3. Include `uart_wire_hex` and `crc16` when you want to pin framing and CRC + behavior for that case. +4. Where the spec is silent, prefer the simplest possible CBOR encoding (no indefinite-length, no tags). If your implementation disagrees with a golden frame, **the golden is the diff --git a/tests/conformance/golden_frames.yaml b/tests/conformance/golden_frames.yaml index 15a7a85..f5d6294 100644 --- a/tests/conformance/golden_frames.yaml +++ b/tests/conformance/golden_frames.yaml @@ -91,6 +91,8 @@ g: 100 b: 0 cbor_hex: "a3 61 72 18 ff 61 67 18 64 61 62 00" + uart_wire_hex: "12 01 01 12 34 7a 22 a3 61 72 18 ff 61 67 18 64 61 62 03 94 ef" + crc16: 0x94ef - name: call with mixed-width sequence number kind: 0x01 diff --git a/tests/conformance/test_conformance.py b/tests/conformance/test_conformance.py index da8ad7e..1b6a164 100644 --- a/tests/conformance/test_conformance.py +++ b/tests/conformance/test_conformance.py @@ -36,6 +36,10 @@ def _build_frame(case: dict) -> bytes: return header + _hex(case.get("cbor_hex", "")) +def _crc16_bytes(case: dict) -> bytes: + return _hex(f"{int(case['crc16']):04x}") + + def load_cases() -> list[dict]: return yaml.safe_load(GOLDEN.read_text(encoding="utf-8")) @@ -90,6 +94,10 @@ def test_uart_wrap_roundtrip(case: dict): assert wire.endswith(b"\x00") assert b"\x00" not in wire[:-1] assert unwrap(wire[:-1]) == frame_bytes + if "uart_wire_hex" in case: + assert wire[:-1] == _hex(case["uart_wire_hex"]) + if "crc16" in case: + assert wire[-3:-1] == _crc16_bytes(case) def test_intent_id_table():