gcf-python 2.2.1__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gcf_python-2.2.1 → gcf_python-2.3.0}/.github/workflows/ci.yml +9 -1
- {gcf_python-2.2.1 → gcf_python-2.3.0}/CHANGELOG.md +29 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/PKG-INFO +58 -10
- {gcf_python-2.2.1 → gcf_python-2.3.0}/README.md +53 -5
- {gcf_python-2.2.1 → gcf_python-2.3.0}/pyproject.toml +5 -5
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/__init__.py +33 -1
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/generic.py +11 -3
- gcf_python-2.3.0/src/gcf/generic_delta.py +487 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_conformance_v2.py +85 -0
- gcf_python-2.3.0/tests/test_generic_delta.py +141 -0
- gcf_python-2.3.0/tests/test_generic_delta_session.py +187 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_roundtrip_v2.py +74 -0
- gcf_python-2.3.0/uv.lock +8 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/.github/FUNDING.yml +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/.github/workflows/publish.yml +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/.gitignore +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/LICENSE +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/assets/gcf-python-diagram.png +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/__main__.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/cli.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/constants.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/decode.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/decode_generic.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/delta.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/encode.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/scalar.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/session.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/stream.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/stream_generic.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/src/gcf/types.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/__init__.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_decode.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_delta.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_encode.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_generic.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_roundtrip.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_session.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_stream.py +0 -0
- {gcf_python-2.2.1 → gcf_python-2.3.0}/tests/test_stream_generic.py +0 -0
|
@@ -13,7 +13,11 @@ jobs:
|
|
|
13
13
|
matrix:
|
|
14
14
|
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
15
15
|
steps:
|
|
16
|
+
# Check out gcf-python and the shared-fixtures gcf repo as SIBLINGS so the
|
|
17
|
+
# conformance runner's ../gcf/tests/conformance path resolves on CI.
|
|
16
18
|
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
path: gcf-python
|
|
17
21
|
- uses: actions/checkout@v4
|
|
18
22
|
with:
|
|
19
23
|
repository: blackwell-systems/gcf
|
|
@@ -22,9 +26,13 @@ jobs:
|
|
|
22
26
|
with:
|
|
23
27
|
python-version: ${{ matrix.python-version }}
|
|
24
28
|
- run: pip install -e ".[dev]" || pip install -e . && pip install pytest
|
|
29
|
+
working-directory: gcf-python
|
|
25
30
|
- name: Unit tests
|
|
26
31
|
run: pytest tests/ -v --ignore=tests/test_conformance_v2.py --ignore=tests/test_roundtrip_v2.py
|
|
27
|
-
|
|
32
|
+
working-directory: gcf-python
|
|
33
|
+
- name: Conformance tests (shared fixtures)
|
|
28
34
|
run: pytest tests/test_conformance_v2.py -v
|
|
35
|
+
working-directory: gcf-python
|
|
29
36
|
- name: Property-based round-trip (100K random + 100K adversarial)
|
|
30
37
|
run: pytest tests/test_roundtrip_v2.py -v
|
|
38
|
+
working-directory: gcf-python
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v2.3.0 (2026-07-12)
|
|
4
|
+
|
|
5
|
+
### Generic-profile delta encoding (SPEC §10a)
|
|
6
|
+
|
|
7
|
+
- Full producer + consumer implementation of generic-profile delta, byte-for-byte interoperable with `gcf-go`:
|
|
8
|
+
- `GenericSet` (keyed record set), `GenericDeltaPayload`
|
|
9
|
+
- `generic_pack_root` (`gcf-pack-root-v1`, generic profile) with a purpose-built cell canonicalization decoupled from the wire cell encoder: collision-free (null/bool/number bare, strings always quoted) and record-safe. Fields and records sort by UTF-8 byte order to match Go's `sort.Strings`.
|
|
10
|
+
- `diff_generic_sets` (the blessed producer path; centralizes the keyed-diff invariants), `encode_generic_full`, `encode_generic_delta`
|
|
11
|
+
- `decode_generic_full`, `decode_generic_delta` (consumer wire parsing)
|
|
12
|
+
- `verify_generic_delta` (atomic apply + `new_root` verification)
|
|
13
|
+
- Re-anchor session helper (SPEC §10a.8): `GenericDeltaSession` (`current_full`, `next`) with `ReanchorPolicy` / `fixed_n(n)` / `size_guard()` cadence policies and `DEFAULT_REANCHOR_N = 15`. Producer-side sugar over the primitives; introduces no new wire syntax (every emission is exactly `encode_generic_full` / `encode_generic_delta` output). Re-anchor cadence is byte-for-byte identical to `gcf-go` (size guard uses UTF-8 byte length to match Go's `len(string)`), verified by the shared `generic-delta-session` conformance fixtures.
|
|
14
|
+
- Delta is opt-in and bilateral; the existing `encode_generic` path is unchanged (backward compatible).
|
|
15
|
+
|
|
16
|
+
### Tests
|
|
17
|
+
|
|
18
|
+
- Unit suite mirroring `gcf-go`: self-proving round-trip (diff -> encode -> apply -> recomputed root), determinism / row-order invariance, no-type-collision canonicalization, every invariant/error path, full-payload wire round-trip, the complete server -> wire -> consumer end-to-end loop, and malformed-wire-fails-closed.
|
|
19
|
+
- Conformance runner support for `generic-pack-root`, `generic-delta`, `generic-delta-verify`, `generic-delta-decode` (12 shared fixtures); verified to produce identical pack roots and delta wire to `gcf-go`.
|
|
20
|
+
- Session helper suite (`test_generic_delta_session.py`) mirroring `gcf-go`: FixedN cadence pattern, size-guard triggering, schema-change forced full, FixedN(15)-over-30-turns count, and the load-bearing consumer-stays-in-sync check under both policies. Conformance runner support for `generic-delta-session` (3 shared fixtures: fixed-N, size-guard, schema-change).
|
|
21
|
+
|
|
22
|
+
## v2.2.2 (2026-07-10)
|
|
23
|
+
|
|
24
|
+
### Fixes
|
|
25
|
+
|
|
26
|
+
- **Losslessness (nested null):** a nested object that is null at an intermediate level (e.g. `{"meta": {"owner": None}}`) is no longer flattened. Previously its leaves encoded as absent (`~`) and unflattened to a missing key, silently dropping the null. Such fields now fall back to the attachment mechanism; a top-level `None` still flattens losslessly (emits `-`, reconstructs via the all-null rule). Enforced by the shared conformance fixtures `flatten/017`–`019`. Prototype pollution does not affect Python (dicts have no mutable prototype).
|
|
27
|
+
|
|
28
|
+
### Tests
|
|
29
|
+
|
|
30
|
+
- `test_flatten_roundtrip`: aligned arrays whose shared fields are fixed-shape nested objects with a field or an intermediate nested level sometimes null/absent — the shape the prior scalar-only generator never produced, leaving the flatten/unflatten path unexercised. Verified to fail on the pre-fix encoder and pass on the fix.
|
|
31
|
+
|
|
3
32
|
## v2.2.1 (2026-06-23)
|
|
4
33
|
|
|
5
34
|
### Flatten Opt-Out
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gcf-python
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary: The AI-native wire format for structured data. 50-92% fewer tokens than JSON. 100% comprehension on every frontier model. Zero dependencies.
|
|
3
|
+
Version: 2.3.0
|
|
4
|
+
Summary: The AI-native wire format for structured data. 50-92% fewer tokens than JSON, with multi-turn delta encoding for agent loops. 100% comprehension on every frontier model. Zero dependencies.
|
|
5
5
|
Project-URL: Homepage, https://github.com/blackwell-systems/gcf-python
|
|
6
|
-
Project-URL: Documentation, https://
|
|
6
|
+
Project-URL: Documentation, https://gcformat.com/
|
|
7
7
|
Project-URL: Specification, https://github.com/blackwell-systems/gcf
|
|
8
8
|
Author: Blackwell Systems
|
|
9
9
|
License: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
|
-
Keywords: gcf,graph,llm,mcp,token-efficient,wire-format
|
|
12
|
-
Classifier: Development Status ::
|
|
11
|
+
Keywords: agents,delta,gcf,graph,llm,mcp,multi-turn,token-efficient,wire-format
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Intended Audience :: Developers
|
|
14
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -32,7 +32,7 @@ Description-Content-Type: text/markdown
|
|
|
32
32
|
|
|
33
33
|
Python implementation of [GCF](https://gcformat.com/) — the most token-efficient wire format for LLMs. A drop-in alternative to JSON and TOON for any structured data.
|
|
34
34
|
|
|
35
|
-
**100% comprehension on every frontier model tested. 29% fewer tokens than TOON, 56% fewer than JSON across 16 datasets. 91.2% on structurally complex code graphs (vs TOON 68.
|
|
35
|
+
**100% comprehension on every frontier model tested. 29% fewer tokens than TOON, 56% fewer than JSON across 16 datasets. 91.2% on structurally complex code graphs (vs TOON 68.8%, JSON 54.1%). 2,400+ LLM evaluations. Zero training.**
|
|
36
36
|
|
|
37
37
|
Docs: [gcformat.com](https://gcformat.com/) · [Playground](https://gcformat.com/playground.html) · [GCF vs TOON](https://gcformat.com/guide/vs-toon.html)
|
|
38
38
|
|
|
@@ -182,6 +182,44 @@ Output:
|
|
|
182
182
|
|
|
183
183
|
Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows. Nested dicts use `## key` section headers.
|
|
184
184
|
|
|
185
|
+
## Generic-Profile Delta (multi-turn)
|
|
186
|
+
|
|
187
|
+
In an agent loop the same keyed table gets re-queried turn after turn. Instead of re-sending the whole table each time, send only the changed rows (SPEC §10a):
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from gcf import GenericSet, diff_generic_sets, encode_generic_delta, verify_generic_delta
|
|
191
|
+
|
|
192
|
+
base = GenericSet(key="id", fields=["id", "status"], rows=[
|
|
193
|
+
{"id": 1001, "status": "pending"},
|
|
194
|
+
{"id": 1002, "status": "shipped"},
|
|
195
|
+
])
|
|
196
|
+
nxt = GenericSet(key="id", fields=["id", "status"], rows=[
|
|
197
|
+
{"id": 1001, "status": "shipped"}, # changed
|
|
198
|
+
{"id": 1003, "status": "pending"}, # added (1002 removed)
|
|
199
|
+
])
|
|
200
|
+
|
|
201
|
+
d = diff_generic_sets(base, nxt)
|
|
202
|
+
wire = encode_generic_delta(d) # ## added / ## changed / ## removed
|
|
203
|
+
held = verify_generic_delta(base, d, d.new_root) # atomic apply + new_root verification
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Opt-in and bilateral, keyed on content-addressed pack roots. By the 5th overlapping call, ~97% fewer tokens than re-sending JSON.
|
|
207
|
+
|
|
208
|
+
### Re-anchor session helper
|
|
209
|
+
|
|
210
|
+
`GenericDeltaSession` manages the delta/re-anchor cadence for you: each `next()` returns either a compact delta or, on its cadence, a full re-anchor (which re-grounds the consumer), updating its held base.
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from gcf import GenericDeltaSession, fixed_n, size_guard
|
|
214
|
+
|
|
215
|
+
sess = GenericDeltaSession(base, tool="orders", policy=size_guard())
|
|
216
|
+
wire = sess.current_full() # transmit the base once to establish it
|
|
217
|
+
for snapshot in stream: # each turn's current GenericSet
|
|
218
|
+
wire, is_full = sess.next(snapshot) # a compact delta, or a periodic full re-anchor
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`fixed_n(15)` re-anchors every N turns; `size_guard()` (recommended) re-anchors once the cumulative delta reaches a full payload's size. It introduces no new wire syntax and the decoder stays cadence-agnostic, so a re-anchor is just the protocol's "full" outcome on a schedule.
|
|
222
|
+
|
|
185
223
|
## API
|
|
186
224
|
|
|
187
225
|
| Function | Description |
|
|
@@ -190,7 +228,11 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
190
228
|
| `encode_generic(data: Any) -> str` | Encode any value to GCF tabular format |
|
|
191
229
|
| `decode(input_text: str) -> Payload` | Parse GCF text back to a Payload |
|
|
192
230
|
| `encode_with_session(p: Payload, s: Session) -> str` | Encode with session deduplication |
|
|
193
|
-
| `encode_delta(d: DeltaPayload) -> str` | Encode a delta (added/removed only) |
|
|
231
|
+
| `encode_delta(d: DeltaPayload) -> str` | Encode a graph delta (added/removed only) |
|
|
232
|
+
| `diff_generic_sets(base, next) -> GenericDeltaPayload` | Diff two keyed record sets (generic profile) |
|
|
233
|
+
| `encode_generic_delta(d) -> str` / `decode_generic_delta(s)` | Generic-profile delta wire (§10a) |
|
|
234
|
+
| `verify_generic_delta(base, d, root) -> GenericSet` | Atomic apply + `new_root` verification |
|
|
235
|
+
| `GenericDeltaSession(base, tool, policy)` | Producer-side re-anchor cadence helper (§10a.8) |
|
|
194
236
|
| `Session()` | Create a new session tracker (thread-safe) |
|
|
195
237
|
|
|
196
238
|
## Types
|
|
@@ -200,7 +242,9 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
200
242
|
| `Payload` | Full GCF payload: tool, budget, symbols, edges, pack root |
|
|
201
243
|
| `Symbol` | Graph node: qualified name, kind, score, provenance, distance |
|
|
202
244
|
| `Edge` | Directed relationship: source, target, edge type |
|
|
203
|
-
| `DeltaPayload` | Diff between two packs: added/removed symbols and edges |
|
|
245
|
+
| `DeltaPayload` | Diff between two graph packs: added/removed symbols and edges |
|
|
246
|
+
| `GenericSet` / `GenericDeltaPayload` | Keyed record set and its generic-profile diff (§10a) |
|
|
247
|
+
| `GenericDeltaSession` | Stateful producer that schedules delta vs full re-anchor (§10a.8) |
|
|
204
248
|
| `Session` | Thread-safe tracker for multi-call deduplication |
|
|
205
249
|
| `KIND_ABBREV` / `KIND_EXPAND` | Bidirectional kind abbreviation dicts |
|
|
206
250
|
|
|
@@ -210,7 +254,7 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
210
254
|
|
|
211
255
|
| | GCF | TOON | JSON |
|
|
212
256
|
|---|---|---|---|
|
|
213
|
-
| **Comprehension** (23 runs, 10 models) | **91.2%** | 68.
|
|
257
|
+
| **Comprehension** (23 runs, 10 models) | **91.2%** | 68.8% | 54.1% |
|
|
214
258
|
| **Generation** (28 runs, 9 models) | **5/5** | 1.0/5 | 5.0/5 |
|
|
215
259
|
| **Input tokens** (500 symbols) | **11,090** | 16,378 | 53,341 |
|
|
216
260
|
| **Output tokens** (100 symbols) | **5,976** | 8,937 | 16,121 |
|
|
@@ -236,7 +280,11 @@ GCF wins 15/16 datasets on the expanded [token efficiency benchmark](https://git
|
|
|
236
280
|
|
|
237
281
|
**Zero runtime dependencies. Permanently.** All six implementations depend only on their language's standard library. No transitive dependencies. No supply chain risk. This is a permanent commitment: GCF will never take on external runtime dependencies. MIT licensed. All implementations support both generic profile (`encodeGeneric`) and graph profile (`encode`). CLI included in all 6 languages.
|
|
238
282
|
|
|
239
|
-
**Specification:** [SPEC v3.2 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with
|
|
283
|
+
**Specification:** [SPEC v3.2 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with 174 conformance fixtures, 43,000,000,000+ lossless round-trips verified across 5 formats and 6 languages. All implementations at v2.2.1+ (Go v1.3.1). Cross-language 6x6 matrix verified.
|
|
284
|
+
|
|
285
|
+
## Adopted by
|
|
286
|
+
|
|
287
|
+
[Chrome DevTools MCP](https://github.com/ChromeDevTools/chrome-devtools-mcp) (46K stars, Google Chrome DevTools team) · [Speakeasy](https://speakeasy.com) (API tooling, customers include Google, Verizon, Mistral AI, DocuSign, Vercel) · [OmniRoute](https://omniroute.online) (6.1K stars) · [NetClaw](https://github.com/automateyournetwork/netclaw) (556 stars) · [ctx](https://github.com/stevesolun/ctx) (510 stars) · [NeuroNest](https://neuronest.cc) · [Open Data Products SDK](https://opendataproducts.org/sdk/) (Linux Foundation) · [Raycast](https://raycast.com/blackwell-systems/json-to-gcf-converter) · [and more](https://gcformat.com/ecosystem/adopters.html)
|
|
240
288
|
|
|
241
289
|
## License
|
|
242
290
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
Python implementation of [GCF](https://gcformat.com/) — the most token-efficient wire format for LLMs. A drop-in alternative to JSON and TOON for any structured data.
|
|
9
9
|
|
|
10
|
-
**100% comprehension on every frontier model tested. 29% fewer tokens than TOON, 56% fewer than JSON across 16 datasets. 91.2% on structurally complex code graphs (vs TOON 68.
|
|
10
|
+
**100% comprehension on every frontier model tested. 29% fewer tokens than TOON, 56% fewer than JSON across 16 datasets. 91.2% on structurally complex code graphs (vs TOON 68.8%, JSON 54.1%). 2,400+ LLM evaluations. Zero training.**
|
|
11
11
|
|
|
12
12
|
Docs: [gcformat.com](https://gcformat.com/) · [Playground](https://gcformat.com/playground.html) · [GCF vs TOON](https://gcformat.com/guide/vs-toon.html)
|
|
13
13
|
|
|
@@ -157,6 +157,44 @@ Output:
|
|
|
157
157
|
|
|
158
158
|
Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows. Nested dicts use `## key` section headers.
|
|
159
159
|
|
|
160
|
+
## Generic-Profile Delta (multi-turn)
|
|
161
|
+
|
|
162
|
+
In an agent loop the same keyed table gets re-queried turn after turn. Instead of re-sending the whole table each time, send only the changed rows (SPEC §10a):
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from gcf import GenericSet, diff_generic_sets, encode_generic_delta, verify_generic_delta
|
|
166
|
+
|
|
167
|
+
base = GenericSet(key="id", fields=["id", "status"], rows=[
|
|
168
|
+
{"id": 1001, "status": "pending"},
|
|
169
|
+
{"id": 1002, "status": "shipped"},
|
|
170
|
+
])
|
|
171
|
+
nxt = GenericSet(key="id", fields=["id", "status"], rows=[
|
|
172
|
+
{"id": 1001, "status": "shipped"}, # changed
|
|
173
|
+
{"id": 1003, "status": "pending"}, # added (1002 removed)
|
|
174
|
+
])
|
|
175
|
+
|
|
176
|
+
d = diff_generic_sets(base, nxt)
|
|
177
|
+
wire = encode_generic_delta(d) # ## added / ## changed / ## removed
|
|
178
|
+
held = verify_generic_delta(base, d, d.new_root) # atomic apply + new_root verification
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Opt-in and bilateral, keyed on content-addressed pack roots. By the 5th overlapping call, ~97% fewer tokens than re-sending JSON.
|
|
182
|
+
|
|
183
|
+
### Re-anchor session helper
|
|
184
|
+
|
|
185
|
+
`GenericDeltaSession` manages the delta/re-anchor cadence for you: each `next()` returns either a compact delta or, on its cadence, a full re-anchor (which re-grounds the consumer), updating its held base.
|
|
186
|
+
|
|
187
|
+
```python
|
|
188
|
+
from gcf import GenericDeltaSession, fixed_n, size_guard
|
|
189
|
+
|
|
190
|
+
sess = GenericDeltaSession(base, tool="orders", policy=size_guard())
|
|
191
|
+
wire = sess.current_full() # transmit the base once to establish it
|
|
192
|
+
for snapshot in stream: # each turn's current GenericSet
|
|
193
|
+
wire, is_full = sess.next(snapshot) # a compact delta, or a periodic full re-anchor
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`fixed_n(15)` re-anchors every N turns; `size_guard()` (recommended) re-anchors once the cumulative delta reaches a full payload's size. It introduces no new wire syntax and the decoder stays cadence-agnostic, so a re-anchor is just the protocol's "full" outcome on a schedule.
|
|
197
|
+
|
|
160
198
|
## API
|
|
161
199
|
|
|
162
200
|
| Function | Description |
|
|
@@ -165,7 +203,11 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
165
203
|
| `encode_generic(data: Any) -> str` | Encode any value to GCF tabular format |
|
|
166
204
|
| `decode(input_text: str) -> Payload` | Parse GCF text back to a Payload |
|
|
167
205
|
| `encode_with_session(p: Payload, s: Session) -> str` | Encode with session deduplication |
|
|
168
|
-
| `encode_delta(d: DeltaPayload) -> str` | Encode a delta (added/removed only) |
|
|
206
|
+
| `encode_delta(d: DeltaPayload) -> str` | Encode a graph delta (added/removed only) |
|
|
207
|
+
| `diff_generic_sets(base, next) -> GenericDeltaPayload` | Diff two keyed record sets (generic profile) |
|
|
208
|
+
| `encode_generic_delta(d) -> str` / `decode_generic_delta(s)` | Generic-profile delta wire (§10a) |
|
|
209
|
+
| `verify_generic_delta(base, d, root) -> GenericSet` | Atomic apply + `new_root` verification |
|
|
210
|
+
| `GenericDeltaSession(base, tool, policy)` | Producer-side re-anchor cadence helper (§10a.8) |
|
|
169
211
|
| `Session()` | Create a new session tracker (thread-safe) |
|
|
170
212
|
|
|
171
213
|
## Types
|
|
@@ -175,7 +217,9 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
175
217
|
| `Payload` | Full GCF payload: tool, budget, symbols, edges, pack root |
|
|
176
218
|
| `Symbol` | Graph node: qualified name, kind, score, provenance, distance |
|
|
177
219
|
| `Edge` | Directed relationship: source, target, edge type |
|
|
178
|
-
| `DeltaPayload` | Diff between two packs: added/removed symbols and edges |
|
|
220
|
+
| `DeltaPayload` | Diff between two graph packs: added/removed symbols and edges |
|
|
221
|
+
| `GenericSet` / `GenericDeltaPayload` | Keyed record set and its generic-profile diff (§10a) |
|
|
222
|
+
| `GenericDeltaSession` | Stateful producer that schedules delta vs full re-anchor (§10a.8) |
|
|
179
223
|
| `Session` | Thread-safe tracker for multi-call deduplication |
|
|
180
224
|
| `KIND_ABBREV` / `KIND_EXPAND` | Bidirectional kind abbreviation dicts |
|
|
181
225
|
|
|
@@ -185,7 +229,7 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
|
|
|
185
229
|
|
|
186
230
|
| | GCF | TOON | JSON |
|
|
187
231
|
|---|---|---|---|
|
|
188
|
-
| **Comprehension** (23 runs, 10 models) | **91.2%** | 68.
|
|
232
|
+
| **Comprehension** (23 runs, 10 models) | **91.2%** | 68.8% | 54.1% |
|
|
189
233
|
| **Generation** (28 runs, 9 models) | **5/5** | 1.0/5 | 5.0/5 |
|
|
190
234
|
| **Input tokens** (500 symbols) | **11,090** | 16,378 | 53,341 |
|
|
191
235
|
| **Output tokens** (100 symbols) | **5,976** | 8,937 | 16,121 |
|
|
@@ -211,7 +255,11 @@ GCF wins 15/16 datasets on the expanded [token efficiency benchmark](https://git
|
|
|
211
255
|
|
|
212
256
|
**Zero runtime dependencies. Permanently.** All six implementations depend only on their language's standard library. No transitive dependencies. No supply chain risk. This is a permanent commitment: GCF will never take on external runtime dependencies. MIT licensed. All implementations support both generic profile (`encodeGeneric`) and graph profile (`encode`). CLI included in all 6 languages.
|
|
213
257
|
|
|
214
|
-
**Specification:** [SPEC v3.2 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with
|
|
258
|
+
**Specification:** [SPEC v3.2 Stable](https://github.com/blackwell-systems/gcf/blob/main/SPEC.md) with 174 conformance fixtures, 43,000,000,000+ lossless round-trips verified across 5 formats and 6 languages. All implementations at v2.2.1+ (Go v1.3.1). Cross-language 6x6 matrix verified.
|
|
259
|
+
|
|
260
|
+
## Adopted by
|
|
261
|
+
|
|
262
|
+
[Chrome DevTools MCP](https://github.com/ChromeDevTools/chrome-devtools-mcp) (46K stars, Google Chrome DevTools team) · [Speakeasy](https://speakeasy.com) (API tooling, customers include Google, Verizon, Mistral AI, DocuSign, Vercel) · [OmniRoute](https://omniroute.online) (6.1K stars) · [NetClaw](https://github.com/automateyournetwork/netclaw) (556 stars) · [ctx](https://github.com/stevesolun/ctx) (510 stars) · [NeuroNest](https://neuronest.cc) · [Open Data Products SDK](https://opendataproducts.org/sdk/) (Linux Foundation) · [Raycast](https://raycast.com/blackwell-systems/json-to-gcf-converter) · [and more](https://gcformat.com/ecosystem/adopters.html)
|
|
215
263
|
|
|
216
264
|
## License
|
|
217
265
|
|
|
@@ -4,17 +4,17 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gcf-python"
|
|
7
|
-
version = "2.
|
|
8
|
-
description = "The AI-native wire format for structured data. 50-92% fewer tokens than JSON. 100% comprehension on every frontier model. Zero dependencies."
|
|
7
|
+
version = "2.3.0"
|
|
8
|
+
description = "The AI-native wire format for structured data. 50-92% fewer tokens than JSON, with multi-turn delta encoding for agent loops. 100% comprehension on every frontier model. Zero dependencies."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
11
11
|
requires-python = ">=3.9"
|
|
12
12
|
authors = [
|
|
13
13
|
{ name = "Blackwell Systems" },
|
|
14
14
|
]
|
|
15
|
-
keywords = ["gcf", "llm", "mcp", "token-efficient", "graph", "wire-format"]
|
|
15
|
+
keywords = ["gcf", "llm", "mcp", "token-efficient", "graph", "wire-format", "delta", "multi-turn", "agents"]
|
|
16
16
|
classifiers = [
|
|
17
|
-
"Development Status ::
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
19
19
|
"License :: OSI Approved :: MIT License",
|
|
20
20
|
"Programming Language :: Python :: 3",
|
|
@@ -32,7 +32,7 @@ gcf = "gcf.cli:main"
|
|
|
32
32
|
|
|
33
33
|
[project.urls]
|
|
34
34
|
Homepage = "https://github.com/blackwell-systems/gcf-python"
|
|
35
|
-
Documentation = "https://
|
|
35
|
+
Documentation = "https://gcformat.com/"
|
|
36
36
|
Specification = "https://github.com/blackwell-systems/gcf"
|
|
37
37
|
|
|
38
38
|
[tool.hatch.build.targets.wheel]
|
|
@@ -39,6 +39,23 @@ from .decode import DecodeError, decode
|
|
|
39
39
|
from .delta import encode_delta
|
|
40
40
|
from .encode import encode
|
|
41
41
|
from .generic import encode_generic, GenericOptions
|
|
42
|
+
from .generic_delta import (
|
|
43
|
+
GenericSet,
|
|
44
|
+
GenericDeltaPayload,
|
|
45
|
+
generic_pack_root,
|
|
46
|
+
diff_generic_sets,
|
|
47
|
+
encode_generic_full,
|
|
48
|
+
encode_generic_delta,
|
|
49
|
+
decode_generic_full,
|
|
50
|
+
decode_generic_delta,
|
|
51
|
+
verify_generic_delta,
|
|
52
|
+
GenericDeltaSession,
|
|
53
|
+
ReanchorPolicy,
|
|
54
|
+
ReanchorMode,
|
|
55
|
+
fixed_n,
|
|
56
|
+
size_guard,
|
|
57
|
+
DEFAULT_REANCHOR_N,
|
|
58
|
+
)
|
|
42
59
|
from .session import Session, encode_with_session
|
|
43
60
|
from .decode_generic import decode_generic
|
|
44
61
|
from .stream import StreamEncoder
|
|
@@ -64,6 +81,21 @@ __all__ = [
|
|
|
64
81
|
"encode_generic",
|
|
65
82
|
"GenericOptions",
|
|
66
83
|
"encode_with_session",
|
|
84
|
+
"GenericSet",
|
|
85
|
+
"GenericDeltaPayload",
|
|
86
|
+
"generic_pack_root",
|
|
87
|
+
"diff_generic_sets",
|
|
88
|
+
"encode_generic_full",
|
|
89
|
+
"encode_generic_delta",
|
|
90
|
+
"decode_generic_full",
|
|
91
|
+
"decode_generic_delta",
|
|
92
|
+
"verify_generic_delta",
|
|
93
|
+
"GenericDeltaSession",
|
|
94
|
+
"ReanchorPolicy",
|
|
95
|
+
"ReanchorMode",
|
|
96
|
+
"fixed_n",
|
|
97
|
+
"size_guard",
|
|
98
|
+
"DEFAULT_REANCHOR_N",
|
|
67
99
|
]
|
|
68
100
|
|
|
69
|
-
__version__ = "
|
|
101
|
+
__version__ = "2.3.0"
|
|
@@ -14,8 +14,8 @@ class GenericOptions:
|
|
|
14
14
|
no_flatten: bool = False
|
|
15
15
|
"""When True, disables promotion of fixed-shape nested objects to path
|
|
16
16
|
columns (e.g. "customer>name"). Nested objects use attachment syntax
|
|
17
|
-
instead.
|
|
18
|
-
|
|
17
|
+
instead. Open-weight models currently comprehend the expanded form
|
|
18
|
+
better; this gap is expected to close."""
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
def encode_generic(data: Any, opts: GenericOptions | None = None) -> str:
|
|
@@ -171,7 +171,15 @@ def _analyze_flattenable(
|
|
|
171
171
|
canonical_shape: dict[str, str] | None = None # key -> "scalar" | "nested"
|
|
172
172
|
|
|
173
173
|
for item in arr:
|
|
174
|
-
if field_name not in item
|
|
174
|
+
if field_name not in item:
|
|
175
|
+
continue
|
|
176
|
+
# A nested (non-top-level) null cannot be flattened losslessly: its leaves
|
|
177
|
+
# would encode as absent ("~") and unflatten back to a missing key, not None.
|
|
178
|
+
# Bail to the attachment path. A top-level None is fine (emits "-" and
|
|
179
|
+
# reconstructs via the all-null rule), so just skip the row from shape analysis.
|
|
180
|
+
if item[field_name] is None:
|
|
181
|
+
if parent_path != "":
|
|
182
|
+
return None
|
|
175
183
|
continue
|
|
176
184
|
v = item[field_name]
|
|
177
185
|
if not isinstance(v, dict):
|