gcf-python 0.5.0__tar.gz → 1.0.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.
Files changed (36) hide show
  1. gcf_python-1.0.0/.github/FUNDING.yml +1 -0
  2. gcf_python-1.0.0/.github/workflows/ci.yml +30 -0
  3. {gcf_python-0.5.0 → gcf_python-1.0.0}/.github/workflows/publish.yml +5 -1
  4. {gcf_python-0.5.0 → gcf_python-1.0.0}/CHANGELOG.md +20 -0
  5. {gcf_python-0.5.0 → gcf_python-1.0.0}/LICENSE +1 -1
  6. {gcf_python-0.5.0 → gcf_python-1.0.0}/PKG-INFO +23 -28
  7. {gcf_python-0.5.0 → gcf_python-1.0.0}/README.md +21 -26
  8. {gcf_python-0.5.0 → gcf_python-1.0.0}/pyproject.toml +2 -2
  9. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/__init__.py +1 -1
  10. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/decode.py +17 -7
  11. gcf_python-1.0.0/src/gcf/decode_generic.py +505 -0
  12. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/delta.py +1 -1
  13. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/encode.py +1 -1
  14. gcf_python-1.0.0/src/gcf/generic.py +179 -0
  15. gcf_python-1.0.0/src/gcf/scalar.py +298 -0
  16. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/session.py +1 -1
  17. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/stream.py +9 -9
  18. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/stream_generic.py +7 -27
  19. gcf_python-1.0.0/tests/test_conformance_v2.py +105 -0
  20. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_decode.py +13 -13
  21. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_encode.py +2 -2
  22. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_generic.py +14 -14
  23. gcf_python-1.0.0/tests/test_roundtrip_v2.py +246 -0
  24. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_stream.py +3 -3
  25. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_stream_generic.py +4 -4
  26. gcf_python-0.5.0/.github/workflows/ci.yml +0 -21
  27. gcf_python-0.5.0/src/gcf/decode_generic.py +0 -255
  28. gcf_python-0.5.0/src/gcf/generic.py +0 -156
  29. {gcf_python-0.5.0 → gcf_python-1.0.0}/.gitignore +0 -0
  30. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/cli.py +0 -0
  31. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/constants.py +0 -0
  32. {gcf_python-0.5.0 → gcf_python-1.0.0}/src/gcf/types.py +0 -0
  33. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/__init__.py +0 -0
  34. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_delta.py +0 -0
  35. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_roundtrip.py +0 -0
  36. {gcf_python-0.5.0 → gcf_python-1.0.0}/tests/test_session.py +0 -0
@@ -0,0 +1 @@
1
+ github: [blackwell-systems]
@@ -0,0 +1,30 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/checkout@v4
18
+ with:
19
+ repository: blackwell-systems/gcf
20
+ path: gcf
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+ - run: pip install -e ".[dev]" || pip install -e . && pip install pytest
25
+ - name: Unit tests
26
+ run: pytest tests/ -v --ignore=tests/test_conformance_v2.py --ignore=tests/test_roundtrip_v2.py
27
+ - name: Conformance tests (133 fixtures)
28
+ run: pytest tests/test_conformance_v2.py -v
29
+ - name: Property-based round-trip (100K random + 100K adversarial)
30
+ run: pytest tests/test_roundtrip_v2.py -v
@@ -8,7 +8,7 @@ jobs:
8
8
  publish:
9
9
  runs-on: ubuntu-latest
10
10
  permissions:
11
- contents: read
11
+ contents: write
12
12
  id-token: write
13
13
  steps:
14
14
  - uses: actions/checkout@v4
@@ -22,3 +22,7 @@ jobs:
22
22
  env:
23
23
  TWINE_USERNAME: __token__
24
24
  TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
25
+ - name: Create GitHub release
26
+ uses: softprops/action-gh-release@v2
27
+ with:
28
+ generate_release_notes: true
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.0.0 (2026-06-10)
4
+
5
+ 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.
6
+
7
+ ### Breaking changes from v0.5.0
8
+
9
+ - `encode_generic` emits `GCF profile=generic` header
10
+ - `decode_generic` requires `GCF profile=` header
11
+ - Strings colliding with typed literals are quoted
12
+ - Full JSON string escaping and number grammar
13
+ - `-` for null, `~` for absent, `^` for nested attachments
14
+ - `##! summary` trailer replaces `## _summary`
15
+ - Graph encoder emits `profile=graph`
16
+
17
+ ### New
18
+
19
+ - `scalar.py`: common scalar grammar (quoting, escaping, parsing, number formatting)
20
+ - Conformance test runner (133 fixtures)
21
+ - Property-based round-trip tests (40M verified, configurable via `GCF_ITERATIONS`)
22
+
3
23
  ## v0.5.0 (2026-06-06)
4
24
 
5
25
  - `GenericStreamEncoder`: zero-buffering tabular streaming encode (begin_array/write_row/end_array/write_kv/write_section/write_inline_array)
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Blackwell Systems
3
+ Copyright (c) 2026 Dayna Blackwell
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gcf-python
3
- Version: 0.5.0
4
- Summary: Python implementation of GCF (Graph Compact Format): token-optimized wire format for LLM tool responses
3
+ Version: 1.0.0
4
+ Summary: Drop-in JSON replacement for AI pipelines. 79% fewer tokens. 90.5% comprehension across 10 models. Zero dependencies.
5
5
  Project-URL: Homepage, https://github.com/blackwell-systems/gcf-python
6
6
  Project-URL: Documentation, https://blackwell-systems.github.io/gcf/
7
7
  Project-URL: Specification, https://github.com/blackwell-systems/gcf
@@ -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
- **79% fewer input tokens than JSON. 75% fewer output tokens. 52% smaller than TOON. 100% LLM comprehension at 500 symbols, where JSON scores 76.9% and TOON scores 92.3%.**
35
+ **79% fewer input tokens than JSON. 63% fewer output tokens. 90.5% average comprehension accuracy across 10 models and 3 providers (four models hit 100%). 1,300+ 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
 
@@ -204,33 +204,18 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
204
204
  | `Session` | Thread-safe tracker for multi-call deduplication |
205
205
  | `KIND_ABBREV` / `KIND_EXPAND` | Bidirectional kind abbreviation dicts |
206
206
 
207
- ## Comprehension Eval
207
+ ## Benchmarks
208
208
 
209
- Rigorous 3-way benchmark (GCF vs TOON vs JSON) at 500 symbols, 200 edges. 13 structured extraction questions sent to an LLM with zero format instructions:
209
+ 1,300+ LLM evaluations across 10 models, 3 providers, and 51 independent test runs.
210
210
 
211
- | Format | Accuracy | Tokens | vs JSON |
212
- |--------|----------|--------|---------|
213
- | **GCF** | **100%** (13/13) | **11,090** | **79% fewer** |
214
- | TOON | 92.3% (12/13) | 16,378 | 69% fewer |
215
- | JSON | 76.9% (10/13) | 53,341 | baseline |
211
+ | | GCF | TOON | JSON |
212
+ |---|---|---|---|
213
+ | **Comprehension** (23 runs, 10 models) | **90.5%** | 68.5% | 53.6% |
214
+ | **Generation** (28 runs, 9 models) | **5/5** | 1.0/5 | 5.0/5 |
215
+ | **Input tokens** (500 symbols) | **11,090** | 16,378 | 53,341 |
216
+ | **Output tokens** (100 symbols) | **5,976** | 8,937 | 16,121 |
216
217
 
217
- GCF is the only format with perfect accuracy at scale, at 32% fewer tokens than TOON.
218
-
219
- Reproduce: `git clone https://github.com/blackwell-systems/gcf-go && cd gcf-go/eval && GOWORK=off go test -run TestComprehension -v -timeout 0`
220
-
221
- ## Token Efficiency (TOON's Own Benchmark)
222
-
223
- Running [TOON's benchmark harness](https://github.com/blackwell-systems/toon/tree/gcf-comparison) with GCF inserted (their datasets, their tokenizer):
224
-
225
- | Track | GCF | TOON | Result |
226
- |-------|-----|------|--------|
227
- | Mixed-structure (nested, semi-uniform) | 170,367 | 227,896 | **GCF 34% smaller** |
228
- | Flat-only (tabular) | 66,029 | 67,837 | **GCF 3% smaller** |
229
- | Semi-uniform event logs | 108,158 | 154,032 | **GCF 42% smaller** |
230
-
231
- GCF wins all 6 datasets. On semi-uniform data (the most common real-world pattern), GCF uses 42% fewer tokens than TOON.
232
-
233
- Reproduce: `git clone https://github.com/blackwell-systems/toon && cd toon && git checkout gcf-comparison && cd benchmarks && pnpm install && pnpm benchmark:tokens`
218
+ GCF wins all 6 datasets on [TOON's own benchmark](https://github.com/blackwell-systems/toon/tree/gcf-comparison). Full results: [gcformat.com/guide/benchmarks](https://gcformat.com/guide/benchmarks.html)
234
219
 
235
220
  ## Links
236
221
 
@@ -243,6 +228,16 @@ Reproduce: `git clone https://github.com/blackwell-systems/toon && cd toon && gi
243
228
  - [GCF vs TOON](https://gcformat.com/guide/vs-toon.html)
244
229
  - [TOON benchmark fork](https://github.com/blackwell-systems/toon/tree/gcf-comparison)
245
230
 
231
+
232
+ <details>
233
+ <summary>More links</summary>
234
+
235
+ - [betterthanjson.com](https://betterthanjson.com)
236
+ - [jsonalternative.com](https://jsonalternative.com)
237
+ - [betterthantoon.com](https://betterthantoon.com)
238
+
239
+ </details>
240
+
246
241
  ## License
247
242
 
248
- MIT
243
+ MIT - [Dayna Blackwell](https://github.com/blackwell-systems)
@@ -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
- **79% fewer input tokens than JSON. 75% fewer output tokens. 52% smaller than TOON. 100% LLM comprehension at 500 symbols, where JSON scores 76.9% and TOON scores 92.3%.**
10
+ **79% fewer input tokens than JSON. 63% fewer output tokens. 90.5% average comprehension accuracy across 10 models and 3 providers (four models hit 100%). 1,300+ 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
 
@@ -179,33 +179,18 @@ Works on dicts, lists, and primitives. Lists of uniform dicts get tabular rows.
179
179
  | `Session` | Thread-safe tracker for multi-call deduplication |
180
180
  | `KIND_ABBREV` / `KIND_EXPAND` | Bidirectional kind abbreviation dicts |
181
181
 
182
- ## Comprehension Eval
182
+ ## Benchmarks
183
183
 
184
- Rigorous 3-way benchmark (GCF vs TOON vs JSON) at 500 symbols, 200 edges. 13 structured extraction questions sent to an LLM with zero format instructions:
184
+ 1,300+ LLM evaluations across 10 models, 3 providers, and 51 independent test runs.
185
185
 
186
- | Format | Accuracy | Tokens | vs JSON |
187
- |--------|----------|--------|---------|
188
- | **GCF** | **100%** (13/13) | **11,090** | **79% fewer** |
189
- | TOON | 92.3% (12/13) | 16,378 | 69% fewer |
190
- | JSON | 76.9% (10/13) | 53,341 | baseline |
186
+ | | GCF | TOON | JSON |
187
+ |---|---|---|---|
188
+ | **Comprehension** (23 runs, 10 models) | **90.5%** | 68.5% | 53.6% |
189
+ | **Generation** (28 runs, 9 models) | **5/5** | 1.0/5 | 5.0/5 |
190
+ | **Input tokens** (500 symbols) | **11,090** | 16,378 | 53,341 |
191
+ | **Output tokens** (100 symbols) | **5,976** | 8,937 | 16,121 |
191
192
 
192
- GCF is the only format with perfect accuracy at scale, at 32% fewer tokens than TOON.
193
-
194
- Reproduce: `git clone https://github.com/blackwell-systems/gcf-go && cd gcf-go/eval && GOWORK=off go test -run TestComprehension -v -timeout 0`
195
-
196
- ## Token Efficiency (TOON's Own Benchmark)
197
-
198
- Running [TOON's benchmark harness](https://github.com/blackwell-systems/toon/tree/gcf-comparison) with GCF inserted (their datasets, their tokenizer):
199
-
200
- | Track | GCF | TOON | Result |
201
- |-------|-----|------|--------|
202
- | Mixed-structure (nested, semi-uniform) | 170,367 | 227,896 | **GCF 34% smaller** |
203
- | Flat-only (tabular) | 66,029 | 67,837 | **GCF 3% smaller** |
204
- | Semi-uniform event logs | 108,158 | 154,032 | **GCF 42% smaller** |
205
-
206
- GCF wins all 6 datasets. On semi-uniform data (the most common real-world pattern), GCF uses 42% fewer tokens than TOON.
207
-
208
- Reproduce: `git clone https://github.com/blackwell-systems/toon && cd toon && git checkout gcf-comparison && cd benchmarks && pnpm install && pnpm benchmark:tokens`
193
+ GCF wins all 6 datasets on [TOON's own benchmark](https://github.com/blackwell-systems/toon/tree/gcf-comparison). Full results: [gcformat.com/guide/benchmarks](https://gcformat.com/guide/benchmarks.html)
209
194
 
210
195
  ## Links
211
196
 
@@ -218,6 +203,16 @@ Reproduce: `git clone https://github.com/blackwell-systems/toon && cd toon && gi
218
203
  - [GCF vs TOON](https://gcformat.com/guide/vs-toon.html)
219
204
  - [TOON benchmark fork](https://github.com/blackwell-systems/toon/tree/gcf-comparison)
220
205
 
206
+
207
+ <details>
208
+ <summary>More links</summary>
209
+
210
+ - [betterthanjson.com](https://betterthanjson.com)
211
+ - [jsonalternative.com](https://jsonalternative.com)
212
+ - [betterthantoon.com](https://betterthantoon.com)
213
+
214
+ </details>
215
+
221
216
  ## License
222
217
 
223
- MIT
218
+ MIT - [Dayna Blackwell](https://github.com/blackwell-systems)
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "gcf-python"
7
- version = "0.5.0"
8
- description = "Python implementation of GCF (Graph Compact Format): token-optimized wire format for LLM tool responses"
7
+ version = "1.0.0"
8
+ description = "Drop-in JSON replacement for AI pipelines. 79% fewer tokens. 90.5% comprehension across 10 models. Zero dependencies."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
11
11
  requires-python = ">=3.9"
@@ -65,4 +65,4 @@ __all__ = [
65
65
  "encode_with_session",
66
66
  ]
67
67
 
68
- __version__ = "0.1.3"
68
+ __version__ = "1.0.0"
@@ -35,7 +35,11 @@ def decode(input_text: str) -> Payload:
35
35
  _parse_header(header[4:], p)
36
36
 
37
37
  if not p.tool:
38
- raise DecodeError("header missing required 'tool' field")
38
+ raise DecodeError("missing_tool: header missing required 'tool' field")
39
+
40
+ # Detect delta mode.
41
+ is_delta = "delta=true" in header
42
+ valid_delta_sections = {"removed", "added", "edges_removed", "edges_added"}
39
43
 
40
44
  # Parse body: symbols and edges.
41
45
  symbols: list[Symbol] = []
@@ -48,6 +52,10 @@ def decode(input_text: str) -> Payload:
48
52
  if not line:
49
53
  continue
50
54
 
55
+ # Skip ##! summary trailer.
56
+ if line.startswith("##! "):
57
+ continue
58
+
51
59
  # Group header.
52
60
  if line.startswith("## "):
53
61
  group = line[3:]
@@ -55,6 +63,8 @@ def decode(input_text: str) -> Payload:
55
63
  bracket_idx = group.find(" [")
56
64
  if bracket_idx >= 0:
57
65
  group = group[:bracket_idx]
66
+ if is_delta and group not in valid_delta_sections:
67
+ raise DecodeError(f"malformed_delta: invalid delta section {group!r}")
58
68
  in_edges = group == "edges"
59
69
  if not in_edges:
60
70
  if group == "targets":
@@ -113,19 +123,19 @@ def _parse_header(fields: str, p: Payload) -> None:
113
123
  def _parse_symbol_line(line: str, distance: int) -> tuple[Symbol, int]:
114
124
  """Parse a symbol line into a Symbol and its local ID."""
115
125
  if not line.startswith("@"):
116
- raise DecodeError(f"expected symbol line starting with @, got {line!r}")
126
+ raise DecodeError(f"invalid_node_line: expected symbol line starting with @, got {line!r}")
117
127
 
118
128
  parts = line.split()
119
129
  if len(parts) < 5:
120
130
  raise DecodeError(
121
- f"symbol line needs at least 5 fields, got {len(parts)} in {line!r}"
131
+ f"invalid_node_line: symbol line needs at least 5 fields, got {len(parts)} in {line!r}"
122
132
  )
123
133
 
124
134
  id_str = parts[0][1:] # strip @
125
135
  try:
126
136
  sym_id = int(id_str)
127
137
  except ValueError as e:
128
- raise DecodeError(f"invalid symbol id {id_str!r}: {e}") from e
138
+ raise DecodeError(f"invalid_symbol_id: invalid symbol id {id_str!r}: {e}") from e
129
139
 
130
140
  kind = parts[1]
131
141
  kind = KIND_EXPAND.get(kind, kind)
@@ -135,7 +145,7 @@ def _parse_symbol_line(line: str, distance: int) -> tuple[Symbol, int]:
135
145
  try:
136
146
  score = float(parts[3])
137
147
  except ValueError as e:
138
- raise DecodeError(f"invalid score {parts[3]!r}: {e}") from e
148
+ raise DecodeError(f"invalid_score: invalid score {parts[3]!r}: {e}") from e
139
149
 
140
150
  provenance = parts[4]
141
151
 
@@ -157,7 +167,7 @@ def _parse_edge_line(line: str, sym_by_id: dict[int, Symbol]) -> Edge:
157
167
  ref = parts[0]
158
168
  lt_idx = ref.find("<")
159
169
  if lt_idx < 0:
160
- raise DecodeError(f"edge line missing '<' separator in {ref!r}")
170
+ raise DecodeError(f"invalid_edge_syntax: edge line missing '<' separator in {ref!r}")
161
171
 
162
172
  target_id_str = ref[1:lt_idx] # strip leading @
163
173
  source_id_str = ref[lt_idx + 2:] # strip <@
@@ -176,7 +186,7 @@ def _parse_edge_line(line: str, sym_by_id: dict[int, Symbol]) -> Edge:
176
186
  source_sym = sym_by_id.get(source_id)
177
187
  if target_sym is None or source_sym is None:
178
188
  raise DecodeError(
179
- f"edge references unknown symbol id(s): target={target_id} source={source_id}"
189
+ f"unknown_edge_reference: edge references unknown symbol id(s): target={target_id} source={source_id}"
180
190
  )
181
191
 
182
192
  edge_type = parts[1]