You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Spec change: optional labeled form for the graph streaming trailer counts (Section 8.4.1)
New Section 8.4.1 defines an opt-in labeled form of the graph streaming trailer's counts field: counts=targets:2,related:1,edges:3 (labeled) as an alternative to the default positional counts=2,1,3. Detection is by the presence of :; the two forms MUST NOT be mixed; the edges: group is always present and last (counts=edges:0 is the minimal trailer); zero-count groups are omitted. Graph profile only (a : in a generic-profile counts is malformed).
Producer-side and non-normative to the consumer: the graph trailer counts are informational (decoder-ignored, Section 13.2). The labeled form is a comprehension aid for known weak consumers; a conforming decoder MUST accept either form (Section 16.3), and neither form changes the decoded payload.
Reconciled the spec with every reference encoder: the graph streaming trailer's counts is the per-distance-group symbol count followed by the edge count (e.g. counts=2,1,3), not a single total. (The generic profile's counts remains one value per [?] header, validated per Section 13.)
Spec correction: .field attachment indentation
Aligned Section 7 with the reference encoders: positional .field attachments are emitted flush-left (same column as the @N row), with the attachment body indented beneath. The prior 2-space form matched no encoder.
All six decoders now reject a .field attachment whose name is neither a ^-marked column of its row nor a >-containing field name (the sole legitimate bare attachment, Section 7.4.6.1.4), instead of silently absorbing it as an undeclared extra field. The old leniency was a round-trip hole: a stray .field decoded to a record shape no encoder produces, and the injected field landed on whichever row parsed last (e.g. a stray .role silently making the last user admin=true). Section 16.5's orphan_attachment row is clarified to state the > exception explicitly, and errors-v2/016_orphan_attachment.json is converted from a decode-success to an error fixture; the legitimate >-named bare attachment stays covered by flatten/016_gt_in_field_name.json. Verified across all six SDKs (conformance + property round-trip green).
All six decoders now 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 second Bob|b@t.com after a row's one ^{name,email} cell was already filled) vanished with no error — silent data loss. Such lines are now rejected as orphan_inline_attachment (errors-v2/037); legitimate object fields (key=value) and in-count rows are unaffected (proven by making the catch-all reject everything and re-running the full conformance + property-round-trip + fuzz suites green).
Encoder fix: order graph edges by source then target (SPEC 16.1)
All six buffered graph encoders now emit edges sorted by source ID, then target ID, then edge type, instead of in input order, satisfying SPEC 16.1 "order edges by source ID then target ID." Edge reordering is decode-invariant (edges are a set) and does not affect pack_root (which sorts edge records independently), so no content addresses change and no existing fixture was affected. The gap had escaped because no fixture carried two or more edges; it is now pinned by graph-encode/003. Streaming edges remain in producer-arrival order (the streaming encoder emits incrementally; producers order edges as they do symbol distance groups).
The streaming graph encoder now emits the trailer counts for distance_N groups (distance >= 3) in group-header emission order, fixing non-deterministic output. gcf-go tracked group counts in a Go map and iterated it to build the trailer, so multiple distance_N groups came out in random order (measured three distinct trailers in twelve runs), violating SPEC 16.1 ("produce deterministic output"). All six SDKs now build the trailer from the recorded group-header emission order (gcf-rust/gcf-swift/gcf-kotlin already did; gcf-python/gcf-typescript are aligned from a fixed targets,related,extended prefix to pure emission order, byte-identical for contract-conformant ascending input). Pinned by new fixtures streaming-v2/010 (positional) and 011 (labeled), which span targets/distance_3/distance_4.
Spec correction: graph tool field is optional
Removed the stale Section 16.5 Missing tool (graph) decoder-reject row and reconciled the Section 16.1 encoder checklist: the graph header tool field is optional (Section 3.2, since v3.1; it is an MCP-response convention, not a requirement, and mandating it would wrongly exclude non-MCP graph producers). Decoders already accept a graph header without tool (graph-decode/003_no_tool_field.json); the Section 16.5 row contradicted that and is now removed.
Conformance
New graph-stream-encode conformance operation with shared fixtures: 004/006 (positional trailer) and 005/007 (labeled trailer, options.labeledTrailerCounts), where 006/007 exercise three distance groups (targets/related/extended) with distinct per-group counts and multiple edges (counts=3,2,1,4 ↔ counts=targets:3,related:2,extended:1,edges:4). Fixtures 008/009 add the zero-edge case (counts=2,1,0 / counts=targets:2,related:1,edges:0), pinning the rule that the edge count is always the last counts entry even when it is 0; this exposed and now guards a divergence where all six encoders dropped the edge count for zero-edge streams (SPEC §8.4 / §8.4.1). Streaming encode previously had only decode fixtures, which is how an earlier Go-only header regression escaped. All six SDKs reproduce these bytes exactly.
New generic-delta-session fixtures exercising the re-anchor cadence (fixed-N, size-guard, and schema-change forced full).
New scripts/coverage-matrix.mjs and generated tests/conformance/COVERAGE.md: cross-reference every fixture against the Section 16.5 decoder strict-mode taxonomy and the conformance operation set, ratcheting in CI (a newly-uncovered condition, a missing required operation, or a stale allow-list entry fails the build). It surfaced the stale Missing tool row (fixed above) and three uncovered conditions; this release adds the verified inline_width_mismatch error fixture (036) and resolves both orphan_attachment and orphan_inline_attachment via decoder hardening (see Decoder hardening above; fixtures errors-v2/016 and errors-v2/037). The Section 16.5 taxonomy is now fully covered (31/31, zero tracked gaps), and the matrix ratchets in CI to keep it that way. The matrix also covers the Section 16.1-16.4 encoder and decoder-accept checklists (each requirement mapped to the fixtures / property tests / invariant scans that exercise it; a requirement with no exercising fixture fails the build) and mechanically scans every fixture's expected output for encoder invariants (no trailing whitespace, graph scores with exactly two decimals, LF line endings). The two previously property-mapped requirements are now pinned by assertion fixtures: symbol ordering by graph-encode/002, distance_N trailer determinism by streaming-v2/010–011, and the round-trip invariant by the roundtrip fixtures plus a new adversarial containers/008 (null, nested section, quote/pipe-escaped scalar, quoted array element). Writing these surfaced a real bug: SPEC 16.1 "order edges by source ID then target ID" was not implemented (the buffered encoder emitted edges in input order); no fixture had 2+ edges, so it had escaped. Fixed below and pinned by graph-encode/003; the checklist is now fully covered (26/26, zero gaps).
Comprehension validation
New eval/graph-trailer-counts study (non-reasoning instruct panel, blank-gated, n=3, four trailer arms across three sizes) motivating Section 8.4.1: emitting per-group trailer counts lifts weak/mid-tier counting comprehension by +33.9pp on average (up to +55.6pp at N=500). The labeled form is >= positional everywhere and decisive where positional regresses (llama-3.1-8b: positional -2pp vs labeled +40pp); frontier models are already at ceiling (+0). See eval/graph-trailer-counts/FINDINGS.md.
Docs
Section 15 comprehension numbers and header date refreshed; the cheatsheet's phantom schema= field removed and generic delta (Section 10a) added; the six api-* reference docs gained the v3.3 generic-delta API surface; the site and spec-reference page cascaded to v3.4.0.