Skip to content

Commit efbecd4

Browse files
WaylandYangclaude
andcommitted
release: v0.3.1 — string pattern + max_length, empirical study, latency A/B
User-facing additions in v0.3.1: Param( ... pattern: str | None = None, # re.fullmatch max_length: int | None = None, # char count ) Both optional, backwards-compatible; enforced at the Bridge. Caught by an empirical study that fed 295 real LLM-emitted tool calls (DeepSeek V3 + Qwen 2.5-72B via SiliconFlow) through every protocol's schema-layer validator. The same study now appears as figure 4 in the paper and as the prose in section 3; the v0.3.1 pattern + max_length fields close the prompt-injection gap (DCP 30% -> 50%, matching OpenAPI's expressiveness at three orders of magnitude less footprint). Also adds tools/bench_latency_iotmcp.py and an iotmcp_echo Arduino sketch: same ESP32-S3, same UART, same asyncio host stack, with the device side speaking newline-delimited JSON like IoT-MCP's reference MCU servers. DCP 15.60 ms vs IoT-MCP 15.59 ms median over 1000 round-trips — capability scoping and full schema validation are free at this scale. Bug fix also worth a release: examples/smart_panel_manifest.yaml's play_tone duration param was type "duration" (which the safety layer coerces to float, breaking the firmware's int reader). Now type "int" with unit "ms". Includes the rebuilt arXiv tarball (docs/paper/dcp-arxiv-v0.3.1.tar.gz) that goes with this release. See CHANGELOG for the full list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8f8005c commit efbecd4

4 files changed

Lines changed: 50 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,54 @@ it reaches 1.0. Pre-1.0 releases may break compatibility.
88

99
## [Unreleased]
1010

11+
## [0.3.1] - 2026-05-24
12+
13+
### Added
14+
15+
- **String parameter constraints** in the manifest: `pattern` (regex,
16+
`re.fullmatch`) and `max_length` for `type: string` params. Both
17+
optional and backward-compatible — absent constraints mean any
18+
string passes. Enforced at the Bridge in `dcp.safety.check_call`;
19+
violations raise `SafetyError("range", ...)` and surface as a
20+
`range` reply status on the wire. Caught by an empirical study
21+
(`tools/gen_llm_corpus.py` + `tools/bench_hallucination_empirical.py`)
22+
where 295 real LLM-emitted tool calls across two models exposed a
23+
prompt-injection gap that pre-v0.3.1 DCP couldn't close.
24+
25+
### Tools
26+
27+
- `tools/gen_llm_corpus.py` — drive an LLM (DeepSeek V3, Qwen2.5-72B
28+
via SiliconFlow) with adversarial prompts, capture the tool calls
29+
it emits.
30+
- `tools/bench_hallucination_empirical.py` — feed the captured corpus
31+
through every protocol's host-side validator (DCP, Raw MCP,
32+
IoT-MCP, OpenAPI) and produce
33+
`docs/paper/figures/hallucination_data.json`.
34+
- `tools/bench_latency_iotmcp.py` + `firmware/esp32/examples/iotmcp_echo`
35+
— apples-to-apples DCP-vs-IoT-MCP latency benchmark on the same
36+
ESP32-S3 hardware over the same UART. Result: 15.60 ms vs 15.59 ms
37+
median round-trip, within 5 µs of each other; capability scoping
38+
and full schema validation add no measurable cost.
39+
40+
### Fixed
41+
42+
- `examples/smart_panel_manifest.yaml` declared `play_tone`'s
43+
`duration` as `type: duration`, which `safety._coerce` converts to
44+
a Python `float` and Bridge serializes as CBOR float64; the device
45+
firmware reads it with `CborReader::read_int()` and rejected every
46+
call. Now declared as `type: int` (the underlying unit, `ms`, is
47+
naturally integer). The four other example manifests still use
48+
`type: duration` and will need the same treatment if they exercise
49+
the path.
50+
- LILYGO T-Panel S3 bring-up: `firmware/esp32/examples/smart_panel`
51+
now uses GPIO 38 for the buzzer instead of GPIO 19 (which is
52+
ESP32-S3 USB D-, and pin-moding it to OUTPUT killed the native
53+
USB-CDC after the first flash). Wire clock dropped from 800 kHz
54+
to 400 kHz to stay inside the XL9535 GPIO expander's I2C max.
55+
`TouchLib`'s CST3240 chip-model define added.
56+
57+
## [0.3.0] - 2026-05-18
58+
1159
### Added
1260

1361
- **Wire-level HMAC-SHA256** (`Frame.encode(wire_secret=...)` / `decode(...)`):

docs/paper/dcp-arxiv-v0.3.1.tar.gz

156 KB
Binary file not shown.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "pydcp"
3-
version = "0.3.0"
3+
version = "0.3.1"
44
description = "Device Context Protocol — Python reference implementation. A bridge between LLM agents and physical devices. Import as `dcp`."
55
readme = "README.md"
66
requires-python = ">=3.11"

src/dcp/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from dcp.simulator import GenericSimulator
99
from dcp.wire import WIRE_VERSION, Frame, Kind, intent_id
1010

11-
__version__ = "0.3.0"
11+
__version__ = "0.3.1"
1212

1313
__all__ = [
1414
"Bridge",

0 commit comments

Comments
 (0)