DCP-AI v2.8.0 — canonicalization profile dcp-jcs-v1 (spec)
What shipped
- New normative document
spec/CANONICALIZATION_PROFILE.md— formalises profiledcp-jcs-v1with eight numbered rules, an edge-case acceptance table, an undefined-handling contract documenting the TypeScript-only asymmetry (omit in objects, serialize asnullin arrays), and a versioning policy for future profiles. - Schema field declared in
schemas/v2/bundle_manifest.schema.json: optionalcanonicalization_profile: "dcp-jcs-v1"on bundle manifests. Per the spec, verifiers that encounter a bundle without the field MUST assumedcp-jcs-v1. Future profiles will make the field required. - Spec § 15 rewritten to reference the full profile document.
- 14 interop edge-case vectors added to
tests/interop/v2/interop_vectors.jsonundercanonicalization.edge_cases. Each SDK's interop test loads the same block and asserts byte-identical output (or matching error) for every vector.
SDK changes
- Python
dcp-ai2.7.1 → 2.8.0 —assert_no_floatsnow accepts floats whose value is a finite integer (1.0,1e2,1.00); they are normalised to integer form beforejson.dumps. Non-integer floats (0.1),NaN, and infinities remain rejected. - Rust
dcp-ai2.7.0 → 2.8.0 —assert_no_floatsnow acceptsNumber(f64)whosefract()is zero. Newformat_numberhelper emits integer-valued floats without decimal point or exponent, matching the other SDKs byte-for-byte. - Go
sdks/go/v2.7.0→v2.8.0— behaviour already aligned (v != math.Trunc(v)check). Version-bump only. - TypeScript
@dcp-ai/sdkstays 2.1.0 — behaviour already aligned. Docstring insdks/typescript/src/core/canonicalize.tsformalises the undefined-vs-null asymmetry.
What is NOT in this release
The schema field is declared but the typed BundleManifest structures in the four SDKs do not expose it, the BundleBuilder types do not emit it by default, and verifiers do not route on it. Code-side wiring of the field across the four SDKs lands in v2.8.1 (see release notes there).
Behavioural compatibility
Bundles produced by previous releases remain valid. The change is additive for SDKs that previously rejected 1.0 / 1.00 / 1e2: inputs that used to throw TypeError / Err now succeed and produce the same canonical output the other SDKs were already producing. No input that previously canonicalised successfully canonicalises differently in 2.8.0.
Registries
- PyPI: https://pypi.org/project/dcp-ai/2.8.0/
- crates.io: https://crates.io/crates/dcp-ai/2.8.0
- Go: `go get github.com/dcp-ai-protocol/dcp-ai/sdks/go/v2@v2.8.0`
- npm `@dcp-ai/sdk`: stays at 2.1.0 (no functional change)