feat(conformance): certify a downstream host's composition, and export the C7 rule - #70
Merged
Merged
Conversation
…t the C7 rule Three gaps found while evaluating stella's conformance against this repo, all of them in the seam between the protocol and a host that is not this repo's. ## 1. A downstream host had no way to be certified `run_host_conformance` takes no arguments: it drives `contextgraph_host::Host` and certifies the reference host, which is the only host in this repository. But `Host::query_all` is not the whole host. It audits budget honesty **per provider** and hands back a fan-out; something above it has to turn N providers' accepted frames into the one frame set that reaches a prompt, and that step makes its own decisions. Nothing checked that step, and the gap is not theoretical. Three providers each returning one honest 400-token frame against a 1000-token query are individually conformant — no `token_cost` lie, no frame flood — and `accepted_frames` yields all three, for 1200 tokens. A host that composed them as-is would pass every check in both existing suites. Adds `composition_conformance`: a `ComposingHost` trait (given these providers and this query, what reached the prompt and what did you drop?) and four checks — the cross-provider token bound (§7), the total partition (every offered frame admitted or reported dropped, never silently truncated, issue #15), the quarantine (§7 B2/B4), and determinism (an unchanged frame set composes to the same render order — the prompt-cache guarantee). `ReferenceComposingHost` (`query_all` + `compose_for_prompt`) passes it, which is what makes the bar satisfiable rather than aspirational. Each check also has a purpose-built saboteur in the unit tests, correct in every respect but one, so green is evidence: a suite whose red is unreachable is decoration. Two things the first draft got wrong, both instructive enough to keep in the comments: - The fixture frames declared a `token_cost` their one-byte bodies did not justify — B3 *violators*. The reference host packs by canonical cost, so it measured 1 where the suite measured 400, and the suite failed a correct host over a fixture defect. Every frame the suite offers now satisfies B3. - The quarantine check used a `token_cost` liar, whose frames are also over the token budget — so a host that skipped the audit entirely still dropped them while packing, and passed for the wrong reason. It now uses a frame flooder, whose frames are individually cheap: only having consulted the audit keeps them out. ## 2. The C7 loopback rule was private `refuse_insecure_transport` is now public. `add_http` already calls it, so C7 holds either way; exporting it lets a host classify a plaintext URL *before* connecting, and report it as the config error it is. The alternative is that every host re-derives "which hosts are loopback" locally and C7 acquires one implementation per host, free to disagree about `[::1]`, `127.0.0.2`, or the casing of `LOCALHOST`. A normative rule with N implementations is N rules. The newly-public contract is pinned by a test over exactly those cases, including the `127.0.0.1.example.com` prefix trap. ## 3. The canary's warning was invisible On 2026-07-29 the downstream canary caught a real break — stella's `add_http` call had not been updated for the C7/C8 credential parameter — emitted its `::warning::`, wrote its step summary, and reported the run as **success**, because it is `continue-on-error` on every event. Nobody saw it; stella stayed thirteen commits behind until a human went looking. A warning on a green run is not a signal. The scheduled run now fails on a downstream break: it gates no PR and blocks no merge, so failing costs nothing and buys a red run plus GitHub's scheduled-failure notification. The `pull_request` path is untouched — a downstream repo still cannot block a merge here. Workspace green: clippy `-D warnings`, `cargo fmt --check`, full test suite.
Reviewer's GuideAdds a downstream host composition conformance suite, exports the C7 insecure transport rule for reuse by other hosts, and strengthens the downstream canary workflow’s signaling semantics while updating SPEC documentation and internal fixtures/utilities to support the new checks. Sequence diagram for ReferenceComposingHost composition flowsequenceDiagram
participant TestSuite
participant ReferenceComposingHost
participant Host
participant ContextProvider
participant FanOut
participant compose_for_prompt
TestSuite->>ReferenceComposingHost: compose(providers, query)
ReferenceComposingHost->>Host: new
loop register providers
ReferenceComposingHost->>Host: register(provider)
end
ReferenceComposingHost->>Host: query_all(query)
Host-->>ReferenceComposingHost: FanOut
ReferenceComposingHost->>ReferenceComposingHost: collect offered frames from FanOut.outcomes
ReferenceComposingHost->>compose_for_prompt: compose_for_prompt(offered, query.max_tokens)
compose_for_prompt-->>ReferenceComposingHost: composed (audit, included, excluded)
ReferenceComposingHost->>ReferenceComposingHost: build admitted from included
ReferenceComposingHost->>ReferenceComposingHost: build dropped as ExcludedFrame from excluded
ReferenceComposingHost-->>TestSuite: Composition{admitted, dropped}
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
macanderson
added a commit
to macanderson/stella
that referenced
this pull request
Jul 30, 2026
…ion vocabulary (#953) Follow-up to #902, which landed the pin bump and deliberately deferred three items. This closes all three, plus a staleness bug the deferral was hiding. > **Stacked on [context-graph-protocol#70](macanderson/context-graph-protocol#70 > The `contextgraph-*` pin points at that PR's branch sha (`c5fb2fe`) and must be > moved to a `main` sha once it lands. Everything below depends on two surfaces it > adds. ## 1. `recall_via_host` is now certified, not asserted CGP #70 adds a composition conformance suite for the step above `Host::query_all` — the merge across providers that turns a fan-out into the frame set a prompt actually gets. That step is `recall_via_host`, which is Stella's own code, which is why no upstream suite was ever going to cover it. The gap it closes is specific: `query_all` audits budget honesty **per provider**. Three providers each returning one honest 400-token frame against a 1000-token query are each within budget and jointly 200 over. Whether the prompt ends up over budget, and whether anyone is told what was dropped to keep it under, is entirely Stella's call. `recall_via_host` now implements `ComposingHost` and passes all four checks: - cross-provider token bound - total partition — every offered frame admitted or reported dropped - quarantine — an audit-rejected provider contributes nothing - deterministic render order It passes **unmodified**, which is the interesting part: these are exactly the properties #713 fixed when the merge had no drop report at all and a budget-squeezed frame simply vanished. This is a guard against a regression this codebase has actually shipped. ## 2. C7 refusals are reported honestly Before: a plaintext `http://` URL to a non-loopback provider surfaced as `Admission::NonConformant` — Stella blaming a remote provider for one character of local config. It was reported that way because the conformance probe connects first, and fixing it needed CGP to export its loopback rule. Now: admission pre-flights the endpoint before the probe and reports `Admission::InsecureTransport`, naming the peer and the fix. Ordering matters on its own terms too — the conformance suite *sends sample queries*, so probing a plaintext peer would put those on the wire. `contextgraph-host` refuses the connection either way, so C7 was never breached, but now nothing tries. The rule is **called, not copied**. "Which hosts are loopback" has edge cases (`[::1]`, all of `127.0.0.0/8`, `LOCALHOST` casing, the `127.0.0.1.example.com` prefix trap); a second copy in Stella would be a second answer. A host may consult a protocol rule; it should not keep its own. Also: a URL the parser rejects is now `Misconfigured` instead of surfacing later as `Unreachable`. ## 3. Attribution — vocabulary aligned, frame-keying scoped `stella_core::context_record::ContextUseKind` is `Selected | Rendered | Cited` — exactly CGP §14's three observations (A2), spelled identically. Now gated, like the `Representation` seam #902 added: if CGP renames an observation or adds a fourth, this fails instead of the two layers quietly describing the same turn in two languages. Frame-keyed attribution (an `AttributionReport` reconcilable against the usage report, A3) is **not** here, and not because it was forgotten. `is_reconcilable` needs every record to name a `FrameId`; the extraction path reads `context_blocks`, which has `content_digest` and `memory_id` but **no provider column**. Two thirds of the triple is recoverable and the third is not — that is a store migration, not a vocabulary alignment. Emitting a report now with `cited` structurally false (it is only observable after the model answers) would be the dead capability surface CGP's own ADR 0004 exists to prevent. ## A correction, and the guard that missed it #902 claimed that dropping `served_frames` weakens UR1. **That was wrong**, and the code comment now says so: every `ContextFrameRef` on the same event carries `provider`, `id`, and `content_digest`, so a billed total *is* walkable back to the exact triples. The `Option`s are meaningful, not lazy — an unmaterialized candidate has no id, a digest-less frame is un-revalidatable by §1 and must be re-queried — and CGP's own `FrameId.content_digest` is optional for the same reason. Chasing that down exposed a real bug. The vendored `docs/context-reuse.md` had its **pin** bumped without its **body** re-fetched, so it claimed a rev it did not match. Upstream had grown §3 (consent scopes and receipts) — 106 lines — and this copy did not have it, while `check-normative-home.sh` went green because it compares shas and never content. Re-vendored from the pinned rev, the now-resolved §3 caveat corrected, and the trap written into the header so the next pin bump does not repeat it. ## One unrelated fix, to unblock the gate `env_files::tests::home_directory_is_never_a_project_scope` fails on macOS on clean `origin/main` — verified at the branch point — and blocks the pre-push gate, so it is fixed here rather than bypassed with `--no-verify`. Its own commit. The behaviour is correct; the test violated its own precondition. `find_base` documents that `start` arrives already resolved (`getcwd`) and so resolves only `$HOME`; the test passed an unresolved `tempdir()`, which on macOS is `/var/folders/…` against a canonicalized `/private/var/folders/…`. Canonicalized, exactly as its sibling three tests below already does for the same reason. ## Gates 1778 tests green across stella-cli/context/graph/core/protocol; clippy `-D warnings` workspace-wide; `cargo fmt --check`; check-file-size; check-normative-home; check-doc-citations. Full pre-push gate green. https://claude.ai/code/session_015x5exqHcz9HkSGFN9Kwhu3 ## Summary by Sourcery Certify host-side composition against the updated Context Graph Protocol, tighten C7 transport security handling for external providers, and align the attribution vocabulary and docs with the new protocol revision. New Features: - Introduce a CGP composition conformance gate for `recall_via_host`, ensuring the host-side merge across providers satisfies protocol composition guarantees. - Add an explicit `InsecureTransport` admission outcome for plaintext non-loopback providers, with operator-facing guidance tied to CGP C7. - Gate the ledger's context-use vocabulary against CGP §14 by asserting that local observation names match the protocol's retrieval-attribution observations. Bug Fixes: - Preflight external HTTP endpoints for transport security and URL validity so C7 violations and unparseable URLs are reported as configuration or security issues rather than generic conformance or reachability failures. - Fix the `home_directory_is_never_a_project_scope` test on macOS by resolving the temporary directory path to match `find_base`'s expectations. Enhancements: - Document that usage reporting still satisfies UR1 without the `served_frames` field by relying on frame references already present in context events. - Clarify and document the relationship between Stella's `ContextUseKind` and CGP's attribution model, including shape and keying differences. Build: - Bump `contextgraph-*` dependencies to the new pinned protocol revision across crates. Documentation: - Re-vendor `docs/context-reuse.md` from the updated CGP revision, incorporating the new consent scopes and receipts section and tightening the normative-home header guidance. - Update other normative design docs to point at the new protocol revision and clarify the intent of the doc-citation checker. Tests: - Add tests that C7 transport security refusals classify plaintext remote providers and loopback exceptions correctly and treat unparseable URLs as configuration errors. - Add a composition conformance test for `recall_via_host` that asserts all protocol composition checks run and pass. - Add a test asserting that the ledger's serialized attribution observation names and count match CGP's retrieval attribution vocabulary. --------- Co-authored-by: Stella Test <test@stella.local>
macanderson
force-pushed
the
feat/host-selfcert-and-c7-preflight
branch
from
July 30, 2026 21:57
c5fb2fe to
733388a
Compare
macanderson
marked this pull request as ready for review
August 1, 2026 01:00
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
macanderson
added a commit
that referenced
this pull request
Aug 1, 2026
…og, and backfill the gaps (#73) CHANGELOG.md relied on every PR remembering to write its own [Unreleased] entry. An audit of the 22 merges since v0.1.0 whose numbers never appear in the file found 9 user-visible changes with no entry at all — including the OCP -> CGP rename itself, the repo's biggest breaking change. The Unreleased section had also accumulated duplicate category headings (two '### Added', two '### Changed', two '### Fixed') from PRs appending their own blocks. Go-forward: .github/workflows/changelog.yml watches pushes to main. When a merge lands without touching CHANGELOG.md, it drafts the missing entries from the merge's actual diff (.github/scripts/changelog-ai.sh, Vercel AI Gateway, degrade-open: no key or a failed call is a log line, never a red check) and proposes them as a bot/changelog PR — a draft for human review, never a direct push. The gap is measured from the last commit that touched CHANGELOG.md, so merging the bot PR resets it, and each run regenerates the whole current gap, so a superseded bot PR loses nothing. Backfill: entries for the rename (#1), frame identity/composition/usage reports (#32), golden wire fixtures (#35), ADR 0007 (#61, #27), composition conformance + the canary scheduled-run gate (#70) — written from each PR's diff, in the file's existing voice. Three further audit hits (#68, #69, #71) turned out to be already covered by newer entries and were left alone. Duplicate category headings merged: one heading per category, Keep-a-Changelog order.
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.
Why
Found while evaluating stella's conformance against this repo. All three gaps are
in the same place: the seam between the protocol and a host that isn't this
repository.
1. A downstream host had no way to be certified
run_host_conformancetakes no arguments. It drivescontextgraph_host::Hostand certifies the reference host — the only host here. But
Host::query_allisnot the whole host: it audits budget honesty per provider and hands back a
fan-out. Something above it turns N providers' accepted frames into the one frame
set that reaches a prompt, and that step makes its own decisions.
Nothing checked that step, and the gap is not theoretical:
A host that composed them as-is would pass every check in both existing suites.
Adds
composition_conformance: aComposingHosttrait — given these providersand this query, what reached the prompt and what did you drop getting there? —
and four checks:
composition-budget-boundmax_tokens, including when only the cross-provider sum overflowscomposition-total-partitioncomposition-quarantinecomposition-determinismReferenceComposingHost(query_all+compose_for_prompt) passes it, which iswhat makes the bar satisfiable rather than aspirational. Each check also has a
purpose-built saboteur in the unit tests — correct in every respect but one — so
green is evidence. A suite whose red is unreachable is decoration.
Two bugs the first draft had, kept in the comments
Both are the kind of mistake the next person writing a check here will make:
token_costtheir one-bytebodies did not justify. The reference host packs by canonical cost, so it
measured 1 where the suite measured 400 — and the suite failed a correct
host over a fixture defect. Every frame the suite offers now satisfies B3.
token_costliar, whose frames are also over the token budget, so a host that skipped the
audit entirely still dropped them while packing. It now uses a frame flooder,
whose frames are individually cheap: only having consulted the audit keeps them
out, which makes the check load-bearing instead of incidental.
2. The C7 loopback rule was private
refuse_insecure_transportis nowpub.add_httpalready calls it, so C7 holdseither way; exporting it lets a host classify a URL before connecting and report
a plaintext endpoint as the configuration error it is, rather than as a connection
failure or a non-conformant provider.
The alternative is that every host re-derives "which hosts are loopback" locally
and C7 acquires one implementation per host, free to disagree about
[::1],127.0.0.2, or the casing ofLOCALHOST. A normative rule with Nimplementations is N rules. The newly-public contract is pinned by a test over
exactly those cases, including the
127.0.0.1.example.comprefix trap.stella consumes it in macanderson/stella#902.
3. The canary's warning was invisible
On 2026-07-29 the downstream canary caught a real break — stella's
add_httpcallhad not been updated for the C7/C8 credential parameter — emitted its
::warning::, wrote its step summary, and reported the run as success,because it is
continue-on-erroron every event. Nobody saw it. stella stayedthirteen commits behind until a human went looking.
A warning on a green run is not a signal; it is a note in a file nobody opens. The
scheduled run now fails on a downstream break: it gates no PR and blocks no
merge, so failing costs nothing and buys a red run plus GitHub's
scheduled-failure notification. The
pull_requestpath is untouched — adownstream repo still cannot block a merge here, which was the right call and is
preserved.
Notes
PROTOCOL_VERSIONchange; nothingpublished or tagged.
SPEC.md§11.1 records the composition harness alongside the host harness, sothe enforcement inventory stays honest about what is and isn't checked — the
suite's own residual (it cannot verify a reason is truthful, only that a drop
is reported) is written down rather than implied.
-D warnings,cargo fmt --check, full test suite.Summary by Sourcery
Add a downstream host composition conformance suite and expose the C7 HTTP loopback rule as public API, while tightening the downstream canary workflow’s signaling on scheduled runs.
New Features:
Enhancements:
CI:
Tests: