feat(protocol): frame representations — full/compact/reference (CGEP phase 2)#41
Merged
Merged
Conversation
…phase 2)
Extend ContextFrame so a frame states *how* it carries its content, per the CGEP
lifecycle build prompt §"ContextFrame representations". Additive and
backward-compatible: `representation` absent ⇒ `full`, and full/legacy frames are
byte-identical on the wire. Satisfies frame_representation_witness.rs (both cases).
Types (contextgraph-types):
- Representation {full|compact|reference}, ContentFidelity, ContentRef, Transform,
InlineContentRequirement.
- ContextFrame: `content` → Option (absent for references); adds representation,
content_fidelity, canonical_content_hash, content_ref, transform,
minimum_content_fidelity, inline_content_requirement, canonical_token_cost,
tokenizer_ref. `content_digest` kept as the inline-content hash (the spec's
content_hash, which feeds FrameId); canonical_content_hash is the full-source
hash. `full`/`reference` constructors + representation_invariants().
- Negotiation: ContextQuery.representation_preferences (+ select_representation);
Capabilities.representations + resolve (+ representations_consistent).
token_cost kept required (u32); canonical_token_cost/tokenizer_ref added
additively. Making token_cost optional reopens PR #33's B3 budget-accounting
decision on the same field, so it is deferred to that reconciliation.
Wire + docs deliverables:
- JSON Schema: new $defs + per-representation invariants (allOf if/then); `content`
no longer globally required.
- examples/reference-messages.json: representation-capable handshake_ack, a query
with representation_preferences, and compact + reference frames (all validate).
- docs/protocol-surface.md representation section; docs/adr/0005; CHANGELOG.
Also unbreaks `main`: contextgraph-host and -conformance did not compile from a
half-applied #37 merge (missing ConsentReceipt/EgressScope/FrameId/DropReason
imports, a DataFlow literal missing egress_scopes, a CHECK_VERIFY_HONESTY test
import, and a stale check-count assertion). Fixed so the workspace builds and the
full suite passes.
There was a problem hiding this comment.
Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
macanderson
marked this pull request as ready for review
July 22, 2026 22:10
macanderson
added a commit
that referenced
this pull request
Jul 22, 2026
Reconcile the pre-freeze normative sweep (#33) with frame representations (#41, full/compact/reference) and context/verify (#38), which landed on main after this branch forked. Key reconciliations: - Capabilities: keep #33's ADR-0004 removal of upsert/subscribe/filters and its `correlation` field; add #41's `verify`/`representations`/`resolve`. - ContextFrame: adopt main's optional `content` + representation model (representation/content_ref/canonical_content_hash/…); rename #33's `canonical_token_cost()` method to `expected_inline_token_cost()` to free the name for #41's `canonical_token_cost` field, and make it handle absent content. - wire::Envelope: keep #33's correlation `id` on query/frames and structured `error` (id/code) AND #41's Verify/Verified variants. - Conformance fixture: keep #33's strict frame-building (valid F5 digests, F4 timestamps) so its enhanced checks pass, grafted with main's verify (verify_honestly/current_digest derived from the fixture's own digests). - schema/examples: union of #33's stricter validations (timestamp/embedding patterns) and #41's representation $defs; drop the removed capability fields. Verified green: cargo build/clippy -D warnings/test, schema validate-examples, and conformance-red.sh (all 14 misbehave modes caught, integrating both #33's and #41's). The frame-representations witness (previously #[ignore]) now passes against main's implementation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
CGEP lifecycle phase 2 — frame representations. A
ContextFramenow stateshow it carries its content, per the lifecycle build prompt
§"ContextFrame representations". This is the implementation the pre-shipped
witness test (
contextgraph-types/tests/frame_representation_witness.rs, addedby #35) has been asserting — and failing on
mainfor.contentcontent_ref+canonical_content_hashcontent_digesttransformfullcompactreferenceAdditive and backward-compatible:
representationabsent ⇒full, andfull/legacy frames are byte-identical on the wire (the field is skipped when
full). Query-only providers are untouched.Feature surface
contextgraph-types):Representation,ContentFidelity,ContentRef,Transform,InlineContentRequirement.ContextFrame.content→Option<String>(absent for references) plus the fields above,canonical_content_hash,canonical_token_cost,tokenizer_ref.ContextFrame::{full,reference}constructors andrepresentation_invariants().ContextQuery.representation_preferences(+select_representation),Capabilities.representations+resolve(+representations_consistent— advertising compact/reference requires resolve).$defs+ per-representation invariants (allOf/if-then,which reject e.g. a reference carrying inline content);
contentno longerglobally required. New
examples/messages (compact + reference frames, arepresentation-capable handshake, a query with preferences) that validate.
docs/protocol-surface.mdrepresentation section; ADR0005; CHANGELOG.The invariants are enforced in three places that agree: Rust, JSON Schema, and
tests.
Scope decision —
token_costkept required (deviation note)The chosen scope said "token_cost → optional". I kept
token_cost: u32required and added
canonical_token_cost/tokenizer_refadditively instead.Making
token_costoptional reopens PR #33's B3 decision on the same field andthe same budget-accounting functions PR #33 rewrites — a guaranteed conflict on
its headline. The witness passes with
token_cost: 0present, so the featuredoes not need it. token_cost-optionality belongs in the B3 reconciliation (below).
Happy to flip it here instead if you'd rather.
Also unbreaks
maincontextgraph-hostandcontextgraph-conformancedid not compile onmain(a half-applied #37 merge): missing
ConsentReceipt/EgressScope/FrameId/DropReasonimports, aDataFlowliteral missingegress_scopes, a missingCHECK_VERIFY_HONESTYtest import, and a stale6→7check-count assertion.Fixed here so the workspace builds — these are pre-existing and unrelated to the
feature, split out in the CHANGELOG's Fixed section.
Verification (local — see note)
Rebase reconciliation for PR #33
This lands to
main; PR #33 then rebases onto it. Expect these to touch the samelines (all trivial, but flagged so nothing surprises):
token_cost == ceil(utf8_len(content)/4).A reference frame has no content and
token_cost: 0, so on rebase B3 mustdefine the absent-content cost as
0. This is the exact normative decision thatstarted this thread.
Capabilities— this addsrepresentations/resolve; PR Pre-freeze normative sweep: SPEC.md, canonical token accounting, conformance that actually catches things #33 removesupsert/subscribe. Same struct, reconcile the literals.import/field/count fixes here overlap.
0005is provisional and may collide with PR Pre-freeze normative sweep: SPEC.md, canonical token accounting, conformance that actually catches things #33's set;renumber on rebase (noted in the ADR).
Known limitation (pre-existing, not fixed here)
The schema lists
provenance/relationsas required, but the Rust type skipsthem when empty (
skip_serializing_if = "Vec::is_empty"). So a bareContextFrame::reference(...)serializes without them and would fail the schema;the bundled examples pass because they include
[]explicitly. This mismatchpre-dates representations (any minimal frame hits it) — reference frames just make
it more visible. Left for a separate schema/wire-strictness pass.