Releases: blackwell-systems/gcf-python
Release list
v2.4.0: Graph delta decode + verify; session + conformance hardening
Fixes
- The conformance runner now hard-fails on any unhandled operation (instead of silently skipping it) and exercises session, delta, roundtrip, and pack-root fixtures end to end; the graph delta wire decode and verify path is now covered, so no operations remain allow-listed.
- Implemented the graph delta wire decoder and verifier (
decode_delta/verify_delta): parse aGCF profile=graph delta=truewire back into removed/added symbols and edge changes, apply them atomically to a base snapshot, recomputepack_root, and reject a wrongnew_rootwithroot_mismatch(SPEC 10.4). The## addedencoder now emits the trailingdistancefield (SPEC 3.4.1, Section 10.1). The sharedgraph-deltafixtures now run end to end: 001 (encode, gains the trailing distance), 002 (verified apply), 003 (root_mismatchrejection). - Session encoding correctness fix.
encode_with_sessionassigned per-response local IDs instead of stable session-global IDs, so the cross-call dedup references (@N # previously transmitted) pointed at the wrong symbols, and the header emitted zero-valuedbudget/tokens/edges. Both are fixed to match the reference; graph session output is now byte-identical across all six SDKs. This had gone undetected because the conformance runner skipped the shared graph-session fixtures (now wired). - Added the graph-profile PackRoot (
pack_root(symbols, edges), gcf-pack-root-v1, SPEC 10.2): the content-addressed sha256 over canonical, independently-sorted symbol/edge records, byte-identical to gcf-go/rust/typescript/swift/kotlin. The conformance runner now exercises the sharedgraph-pack-rootfixtures, which it had been skipping (so this primitive was previously unimplemented and untested). - Buffered graph encoder now matches the reference byte-for-byte: symbols are ordered by distance then descending score with local IDs assigned in output order, and the header omits
budget/tokens/edgeswhen zero (previously symbols kept input order and zero-valued header fields were always emitted). The conformance runner now exercises the sharedgraph-encodefixtures (001-003), which it had been skipping - which is how this divergence went uncaught. - Buffered graph encoder: order edges by source ID, then target ID, then edge type (SPEC 16.1), instead of emitting them in input order. Decode-invariant (edges are a set) and does not affect
pack_root(which sorts edge records independently), so no content addresses change. Pinned by shared fixturegraph-encode/003. Streaming edges remain in producer-arrival order. - Decoder: reject an orphan
.fieldattachment (a.fieldwhose name is neither a^-marked column of its row nor a>-containing field name, SPEC 7.4.6.1.4) instead of silently absorbing it as an undeclared extra field. Such a stray attachment previously decoded to a record no encoder produces, silently injecting a field onto the last-parsed row (a lossless round-trip hole); now rejected per SPEC 16.5 (orphan_attachment). - Decoder: reject an orphan positional inline body (a pipe-delimited line with no eligible
^{}attachment-marker cell) instead of silently dropping it. The object-body parser previously skipped any unrecognized line, so a stray positional body (e.g. a secondBob|b@t.comafter a row's one inline cell was filled) vanished with no error (silent data loss); now rejected per SPEC 16.5 (orphan_inline_attachment). - Graph streaming trailer: the edge count is now always the last
countsentry, even when the stream has no edges (positionalcounts=2,1,0; labeledcounts=…,edges:0). A zero-edge stream previously dropped it, violating the SPEC §8.4 / §8.4.1 rule that the edge count is always present and last (the invariant that keeps the positional form unambiguous). The graph trailer is decoder-ignored, so this changes producer output only.
Streaming: opt-in labeled trailer counts (SPEC §8.4.1)
- New
labeled_trailer_countskeyword onStreamEncoder. When set, the##! summarygraph streaming trailer emitscounts=in the labeled formlabel:countper group (e.g.counts=targets:2,related:1,edges:3) instead of the default positional values-only form (counts=2,1,3). Default false is byte-identical to prior output. - Opt-in and non-breaking: a producer-side comprehension aid for known weak consumers. The trailer counts remain informational (decoder-ignored) in both forms; neither changes the decoded payload. Mirrors the
gcf-goreference.
Conformance and docs
- Streaming graph trailer now emits
distance_Ngroup counts in pure group-header emission order (dropping a fixedtargets,related,extendedprefix), matching the other SDKs and deterministic per SPEC 16.1. Byte-identical for contract-conformant (ascending-distance) input; pinned by shared fixturesstreaming-v2/010–011. - The conformance runner now executes the
graph-stream-encodefixtures (streaming-encode parity, previously decode-only): fixture 004 (positional trailer) and 005 (labeled trailer). - README: corrected the streaming example trailer from the defunct
## _summary … sections=to the real##! summary … counts=; README now leads with the project diagram. - Added a generic-delta fuzz test (decoder never crashes; string round-trip).
Full Changelog: v2.3.0...v2.4.0
v2.3.0
Generic-profile delta + re-anchor session helper (SPEC §10a)
Delta encoding comes to the generic profile — the multi-turn compression that JSON and TOON structurally lack — plus a producer-side re-anchor helper. Byte-for-byte interoperable across all six GCF SDKs (Go, Python, TypeScript, Rust, Swift, Kotlin) against a shared conformance suite.
Generic-profile delta (§10a)
Keyed row diffs: send only what changed (## added / ## changed / ## removed) instead of re-sending the whole table each turn.
GenericSet+GenericDeltaPayload;generic_pack_root(content-addressedgcf-pack-root-v1)diff_generic_sets(producer) ·encode_generic_full/encode_generic_delta·decode_generic_full/decode_generic_delta·verify_generic_delta(atomic apply +new_rootverification)- Opt-in and bilateral; the existing encode path is unchanged.
Re-anchor session helper (§10a.8)
GenericDeltaSession — a thin stateful producer that manages the re-anchor cadence for you. Each next() returns either a compact delta or, on its cadence, a full re-anchor, updating its held base.
fixed_n(n)(default N=15) orsize_guard()(size-adaptive, production-recommended)- No new wire syntax; cadence knobs are never wire fields, so the decoder stays cadence-agnostic. A schema change forces a full.
Why it matters
Across a 50-turn comprehension study, six of seven cleanly-measured models comprehend delta as well as full-resend at a fraction of the tokens; the one model that drifts at depth is closed by the re-anchor.
Correctness
Byte-for-byte identical wire and pack roots across all six SDKs, verified by shared conformance fixtures (generic-pack-root, generic-delta, generic-delta-session). MIT, zero runtime dependencies. Ships with GCF SPEC v3.3.0.
Install: pip install gcf-python
Adopted by
Headlined by Chrome DevTools MCP — the #1 most-starred MCP server on GitHub (46K★), built by the Google Chrome DevTools team, which merged GCF as an experimental data format (--experimentalDataFormat=gcf) after a 4-round review.
Also running in production across the ecosystem:
- OmniRoute (15.6K★) — AI gateway/proxy; GCF vendored into its compression engine
- Raycast (7.5K★) — JSON→GCF converter extension in the Store
- Speakeasy —
oq --format gcffor OpenAPI query output - NetClaw (556★) — network automation; switched from TOON to GCF
- ctx (510★) — Claude Code tool-recommender;
pip install "claude-ctx[gcf]" - bb — Bitbucket Cloud CLI/TUI;
--format gcf - NeuroNest — agent-first IDE
- Open Data Products SDK — Linux Foundation data-product toolkit
- knowing · agent-lsp — code-intelligence + LSP-orchestration MCP servers
Using GCF in production? Open an issue to be listed.
v2.2.2
Patch release: a losslessness fix in nested-object flattening. No API changes; recommended for all users.
🐛 Fixes
- Losslessness: null nested objects are no longer dropped. A nested object that was an object in some records and
nullat an intermediate level in others (e.g.{"meta": {"owner": null}}) was being flattened, and on decode thenullreconstructed as a missing key instead ofnull, silently losing data. Such fields now fall back to the attachment encoding, which round-trips exactly. A top-levelnullstill flattens (it emits-and rebuilds via the all-null rule), so compression is unaffected for that case.
✅ Tests
- Added
test_flatten_roundtrip: aligned arrays whose shared fields are fixed-shape nested objects with a field or an intermediate level sometimes null/absent, the shape the prior scalar-only generator never produced. Verified failing on the pre-fix encoder and passing on the fix at 500k iterations.
This is a format-level bug, fixed identically across the GCF SDKs (TypeScript / Go / Python / Rust / Swift / Kotlin); it is locked in by shared conformance fixtures (flatten/017–019) that this SDK's conformance suite runs against the gcf spec repo.
Full Changelog: v2.2.1...v2.2.2
v2.2.1
Flatten Opt-Out
encode_generic(data, GenericOptions(no_flatten=True))disables nested object flattening- Backward compatible:
encode_generic(data)unchanged
Bug Fixes
- Field names containing
>excluded from tabular columns (spec rule 7.4.6.1.4) - Field names containing
>no longer eligible for flattening analysis - Decoder no longer treats literal
>in key names as a path separator - Decoder accepts orphan attachments (fields excluded from column list)
- 200K round-trips (both modes, > in keys) zero failures; 12 targeted edge case tests
Full changelog: v2.2.0...v2.2.1
Full Changelog: v2.2.0...v2.2.1
v2.2.0: Nested Object Flattening (Spec v3.2)
Nested Object Flattening
Encoder automatically flattens fixed-shape nested objects into > path column names. Decoder reconstructs nesting from > paths.
- 20-48% fewer tokens on deeply nested API data
- 100% comprehension on every frontier model
- Zero regression on 1M random + 1M adversarial round-trips
- 17-format mega-gauntlet: PERFECT data integrity
- Falls back to attachment mechanism for non-flattenable cases
- Round-trip guarantee preserved
Full Changelog: v2.1.1...v2.2.0
v2.1.1
Patch release. Fixes encoder quoting for edge cases involving bracket-colon patterns in string values. 10M fuzz iterations, zero failures.
Full Changelog: v2.1.0...v2.1.1
v2.1.0
Spec v3.1 Conformance
Spec change
toolfield in graph profile header is now optional (SHOULD be present for MCP, not required)
Bug fixes
- Quote strings containing commas in scalar values
- Decode v2-format indented attachments in tabular rows
- Reject duplicate attachments on the same row
- Reject orphan attachments on rows without
^cells
Conformance
- 157/157 fixtures passing
- 23.25B+ round-trips verified across all 6 implementations, zero failures
Full spec release: gcf v3.1.0
v2.0.0: Inline Schema Encoding
v2.0.0: Inline Schema Encoding
The generic profile encoder now produces inline schema format for nested objects with 3+ scalar fields. This is a breaking change from v1.x output.
Breaking Changes
encodeGenericoutput format changed (inline schemas, no attachment indentation)- Decoders no longer accept v1.x indented attachment syntax
- Comma no longer quoted in pipe-delimited contexts (only in comma-delimited inline arrays)
- Strings starting with digits no longer quoted unless they match JSON number grammar
New Features
- Inline object schema (
^{fields}): nested objects encoded positionally - Shared array schemas: identical nested arrays omit field headers after first row
- 25.5% fewer tokens than TOON across 15 real-world datasets
Integrity
- 1B+ lossless round-trip iterations across 6 language implementations
- 100% comprehension accuracy on every frontier model tested
- 156 conformance fixtures passing
Full spec: https://github.com/blackwell-systems/gcf/releases/tag/v3.0.0
v1.0.1: CLI generic profile
- CLI:
encode-genericanddecode-genericsubcommands python -m gcfentry point- Both graph and generic profiles supported from the command line
gcf-python v1.0.0
SPEC v2.0 implementation
126/133 conformance fixtures passing (7 skipped: session, delta, binary UTF-8, negative zero, graph encode). 40M property-based round-trips with zero failures.
Breaking changes from v0.5.0
encode_genericemitsGCF profile=genericheaderdecode_genericrequiresGCF profile=header- Strings colliding with typed literals are quoted
- Full JSON string escaping and number grammar
-for null,~for absent,^for nested attachments##! summarytrailer replaces## _summary- Graph encoder emits
profile=graph
Install
pip install gcf-python==1.0.0