diff --git a/.github/ISSUE_TEMPLATE/spec-feedback.yml b/.github/ISSUE_TEMPLATE/spec-feedback.yml index b220237..b70a79a 100644 --- a/.github/ISSUE_TEMPLATE/spec-feedback.yml +++ b/.github/ISSUE_TEMPLATE/spec-feedback.yml @@ -6,14 +6,13 @@ body: - type: markdown attributes: value: | - The formal v1 public comment period closed on 24 July 2026. This template - remains available for questions, unclear or contradictory requirements, + Use this for questions, unclear or contradictory requirements, implementation evidence, and gaps in the specification as written. For a new capability or change in behaviour, submit a short human-written note to [proposals/](../tree/main/proposals) instead. Please wait for explicit maintainer alignment before beginning implementation. New - proposals are not automatically part of the v1 scope. + proposals are not automatically accepted into a 1.x release. For a concrete bug in a schema file or a worked example, use the **Schema or example bug** template instead. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index cc956e9..1091278 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,5 +1,5 @@ # Code of conduct -Participation in this project - issues, pull requests, and the public comment process - is expected to be professional and respectful. Critique ideas, not people. Harassment, personal attacks, and bad-faith disruption are not tolerated. +Participation in this project - issues, pull requests, and proposals - is expected to be professional and respectful. Critique ideas, not people. Harassment, personal attacks, and bad-faith disruption are not tolerated. The maintainer may edit, lock, or remove contributions that breach this, and may block repeat offenders. To report a problem, email alex@spurcoalition.org. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1f6b20..e3bcd17 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,8 +10,11 @@ This repo contains the **specification** - the data model, event types, privacy | [telemetry-session.json](./telemetry-session.json) | JSON Schema for session validation | | [telemetry-event.json](./telemetry-event.json) | JSON Schema for standalone event validation | | [telemetry-event-batch.json](./telemetry-event-batch.json) | JSON Schema for event batch validation | +| [manifest.json](./manifest.json) | JSON Schema for the well-known manifest | +| [SCOPE.md](./SCOPE.md) | The boundary between core, profiles and governing terms | +| [proposals/](./proposals/) | Human-written proposals for new capabilities | | [tests/](./tests/) | Conformance test suite | -| [GOVERNANCE.md](./GOVERNANCE.md) | Stewardship and preview-status policy | +| [GOVERNANCE.md](./GOVERNANCE.md) | Stewardship, versioning status, relationship to profiles | | [LICENSE](./LICENSE) | Apache License 2.0 | ## Proposing changes @@ -75,13 +78,14 @@ implementation pull request should: From a clean checkout, with no setup beyond [uv](https://docs.astral.sh/uv/): ```sh -uv run --with jsonschema python tests/validate.py # conformance suite -uv run --with jsonschema python tests/check_examples.py # examples in the spec validate against the schemas +uv run --with "jsonschema[format-nongpl]" python tests/validate.py # conformance suite +uv run --with "jsonschema[format-nongpl]" python tests/check_examples.py # examples in the spec validate against the schemas +uv run --with "jsonschema[format-nongpl]" python tests/mutation_smoke.py # suite-weakening mutations are caught ``` -(Without uv: `pip install jsonschema` then `python3 tests/validate.py`.) +(Without uv: `pip install "jsonschema[format-nongpl]"` then `python3 tests/validate.py`.) -`check_examples.py` validates every complete worked example in SPECIFICATION.md and README.md against its schema; an example that no longer matches its schema fails the build. Both commands run in CI on every pull request (`.github/workflows/ci.yml`). +`check_examples.py` validates every complete worked example in SPECIFICATION.md and README.md against its schema; an example that no longer matches its schema fails the build. All three commands run in CI on every pull request (`.github/workflows/ci.yml`). ## Conformance levels diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 36cecca..491773c 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -16,24 +16,22 @@ The SPUR Coalition stewards the specification and holds this repository. The sta ## Who the SPUR Coalition is -The SPUR Coalition is a group of publishers and content owners that maintains the Content Telemetry standard. It holds the intellectual property through the preview period and releases the standard under Apache 2.0 from 12 June 2026. +The SPUR Coalition is a group of publishers and content owners that maintains the Content Telemetry standard and releases it under Apache 2.0. -Contributing to the standard does not require membership. The wire format is developed in the open, and anyone - content owner, agent operator, intermediary, or implementer - can take part through the issue tracker and the process described in the [README](./README.md#consultation-record). +Contributing to the standard does not require membership. The wire format is developed in the open, and anyone - content owner, agent operator, intermediary, or implementer - can take part through the issue tracker and the process described in the [README](./README.md#feedback). The standard is maintained by Alex Springer (alex@spurcoalition.org). -## Version 1.0 and decisions - -The specification reached 1.0 on 2 September 2026, following the public consultation of 12 June to 24 July 2026 and the release-candidate work recorded on the issue tracker. +## Decisions Decisions follow the proposal and alignment process in [CONTRIBUTING.md](./CONTRIBUTING.md): anyone may propose a change, a maintainer records the disposition publicly on the issue tracker, and the SPUR Steering Board approves releases. The tracker and pull-request history are the public decision record. Minor versions add optional fields and event types; breaking changes require a major version (SPECIFICATION.md section 12). ## How to participate - File questions and bugs on the [issue tracker](https://github.com/SPUR-Coalition/telemetry/issues) (see the templates). -- See the [consultation record](./README.md#consultation-record). The formal - v1 comment window is closed, but concrete bugs and implementation evidence - remain welcome on the issue tracker. +- The issue tracker and pull-request history are the public decision record + (see the [README](./README.md#feedback)); concrete bugs and implementation + evidence are always welcome. - Propose new capabilities or changes in behaviour as a short human-written note in [`proposals/`](./proposals/), following [CONTRIBUTING.md](./CONTRIBUTING.md). diff --git a/README.md b/README.md index 3ddad71..4a97c3b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Signal format for AI content usage reporting.** -**Version 1.0** is the current specification, published 2 September 2026. It replaces the v0.1 preview; the changes and migration steps are recorded in [SPECIFICATION.md section 12.1](./SPECIFICATION.md#121-migration-from-the-v01-preview). +**Version 1.0** is the current specification. Migration from the v0.1 preview is recorded in [SPECIFICATION.md section 12.1](./SPECIFICATION.md#121-migration-from-the-v01-preview). ## Contents @@ -12,7 +12,7 @@ - [Repo contents](#repo-contents) - [Example](#example) - [Relationship to other protocols](#relationship-to-other-protocols) -- [Consultation record](#consultation-record) +- [Feedback](#feedback) - [Open questions in v1](#open-questions-in-v1) - [Versioning](#versioning) @@ -40,7 +40,8 @@ The gaps between stages show how content was used: - **Retrieval without grounding** - your content was fetched but not used - **Grounding without citation** - your content influenced the answer but you got no credit -- **Citation without engagement** - your content was cited but the user didn't click through +- **Citation without presentation** - your content was credited in the output but the credit never reached the user +- **Presentation without engagement** - your link was shown but the user didn't click through The grounding event captures the boundary "this content entered the agent's generation context." It is architecture-neutral and decoupled from retrieval: content cached by the agent for days still produces a grounding event in every session it influences. @@ -152,30 +153,23 @@ The content owner can derive: FT article `abc123` was in context for the respons Content Telemetry is focussed on **reporting**, while content **access** protocols (Really Simple Licensing, peek-then-pay, IAB CoMP, bilateral APIs) aim to govern how agents discover and license content. The `license_ref` field on events connects telemetry to whatever access protocol issued the licence, but the schemas are independent - telemetry works with any access protocol, or none. -## Consultation record +## Feedback -The public comment period ran from **12 June to 24 July 2026**. Thank you to -everyone who opened an issue, submitted a pull request, joined a working -session or supplied implementation evidence. - -The consultation produced 29 specification issue threads, three profile issue -threads and five pull requests. Every thread carries a recorded outcome, and -the issue tracker and pull-request history remain the public decision record. -The accepted core changes were tracked on the -[v1 release candidate milestone](https://github.com/SPUR-Coalition/telemetry/milestone/1), -merged on the `v1-draft` integration line, and published as version 1.0 on -2 September 2026. - -Concrete schema, fixture and documentation bugs may be filed using the -*Schema or example bug* template, and questions or unclear requirements using -*Spec feedback / open question*. For a new capability or change in behaviour, -submit a short human-written note to [`proposals/`](./proposals/) and wait for +File concrete schema, fixture and documentation bugs with the *Schema or +example bug* template, and questions or unclear requirements with *Spec +feedback / open question*. For a new capability or change in behaviour, submit +a short human-written note to [`proposals/`](./proposals/) and wait for explicit maintainer alignment before beginning implementation (see -[CONTRIBUTING.md](./CONTRIBUTING.md)). Pull requests remain welcome for -specific fixes. Feedback on accreditation or the conformance mark belongs on -the [profile +[CONTRIBUTING.md](./CONTRIBUTING.md)). Pull requests are welcome for specific +fixes. Feedback on accreditation or the conformance mark belongs on the +[profile repository](https://github.com/SPUR-Coalition/telemetry-profile/issues). +The [issue tracker](https://github.com/SPUR-Coalition/telemetry/issues) and +pull-request history are the public decision record, including the v1 +consultation (12 June - 24 July 2026) and the +[v1 release candidate milestone](https://github.com/SPUR-Coalition/telemetry/milestone/1). + ## Open questions in v1 The following areas are expected to develop in 1.x minor versions and profiles, with implementer input: @@ -184,7 +178,7 @@ The following areas are expected to develop in 1.x minor versions and profiles, **Event volume at scale.** A single deep-research query can produce 100+ retrieval events and dozens of grounding/citation events. The session document format already handles transport - one POST with all events after the session ends, not one request per event. Volume management beyond that (storage, processing, consumer-side aggregation) is an implementation concern, not a protocol gap. Version 1 adds an explicit coverage declaration - `complete`, `sampled`, `aggregated` or `selected` (section 5.7.6) - and a manifest field for it (section 8.5); the standard still sets no default for reporting granularity, leaving it to profiles and deployments. -**Verification of grounding and citation.** Grounding and citation events are reported by the agent, which is also the party that may owe compensation under a licence. In v1, manifest signing is informational: consumers may verify signatures but are not required to, and the specification defines no required proof binding an event to its emitter (sections 8.4 and 8.9). The events attribution depends on are therefore self-reported by the reporting party. Verifiable credentials and signed events are deferred (section 8.9). One corroboration mechanism works without signing: the `Content-Telemetry-ID` field correlates an agent-reported retrieval with an origin- or edge-reported one (section 7.2), but it covers retrieval only - grounding, citation, presentation, and engagement have no independent observer. Signing, even once required, would prove who reported an event, not that the event is true or that all qualifying events were reported. Input is wanted on what a verification layer should cover and where it belongs. Mechanisms that test truthfulness and completeness rather than origin, such as sampled audits or publisher-seeded canary content, are of particular interest. +**Verification of grounding and citation.** Grounding and citation events are reported by the agent, which is also the party that may owe compensation under a licence. In v1, manifest signing is informational: consumers may verify signatures but are not required to, and the specification defines no required proof binding an event to its emitter (sections 8.4 and 8.9). The events attribution depends on are therefore self-reported by the reporting party. Verifiable credentials and signed events are deferred (section 8.9). One corroboration mechanism works without signing: the `Content-Telemetry-ID` header correlates an agent-reported retrieval with an origin- or edge-reported one (section 7.2), but it covers retrieval only - grounding, citation, presentation, and engagement have no independent observer. Signing, even once required, would prove who reported an event, not that the event is true or that all qualifying events were reported. Input is wanted on what a verification layer should cover and where it belongs. Mechanisms that test truthfulness and completeness rather than origin, such as sampled audits or publisher-seeded canary content, are of particular interest. **Reporting granularity.** The standard sets no default for reporting granularity, leaving it to profiles and deployments (see *Event volume* above). The SPUR profile requires event-level delivery and does not permit aggregation. Version 1 answers the first half of the question: coverage modes are defined once, in section 5.7.6, so that profiles reference them rather than each define their own. How event-level delivery scales for the highest-volume case remains open. diff --git a/SCOPE.md b/SCOPE.md index 72e3888..877b437 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -26,4 +26,4 @@ An implementation uses the core schema and specification, a small profile bundle For example, an operator could choose a SPUR advertising deployment recipe and supply the publisher endpoints and commercial requirements. The SDK or collector would resolve the required delivery, advertising and evidence capabilities at startup. The agent would then emit ordinary lifecycle events; the collector would route publisher reports and send relevant evidence to the configured verification service. The developer would not select profiles or negotiate capabilities inside each agent turn. -The closed consultation feeds a v1 release candidate rather than an intermediate v0.2 release. Compatibility with a mistake in the preview version is not a constraint. A breaking change is acceptable when it makes v1 easier to implement. It must include migration notes and replacement fixtures, and must not silently change meaning within an existing version. +Breaking changes follow the versioning policy in SPECIFICATION.md section 12: they require a major version, migration notes and replacement fixtures, and meaning never changes silently within an existing version. diff --git a/SPECIFICATION.md b/SPECIFICATION.md index 1c9855d..522b93e 100644 --- a/SPECIFICATION.md +++ b/SPECIFICATION.md @@ -63,7 +63,7 @@ The five-stage lifecycle reports content use observable at inference time: ident Retrieval is the boundary case. A crawl whose purpose is training or index building can be reported as a `content_retrieved` event, and `purpose` (section 6.2) distinguishes it, but the event is non-attributable: no grounding, citation, presentation or engagement follows it. What the system then does with the content, whether it enters a training corpus, a fine-tuning set, an embedding store or a search index, is outside this specification. Nothing here reports that a model was trained on a work, and a conforming implementation says nothing either way about it. -Using such a store at inference time is inside scope. When an index built over a content owner's material is queried during a response and returns content that grounds the answer, that is a `content_grounded` event like any other, with `source_role: index` on the retrieval that served it (section 4.4). The line is between constructing a derived artefact and using one to answer a query, not whether an index was involved. +Using such a store at inference time is inside scope. When an index built over a content owner's material is queried during a response and returns content that grounds the answer, that is a `content_grounded` event like any other, with `source_role: index` on the retrieval that served it (section 4.4). The line is between constructing a derived artifact and using one to answer a query, not whether an index was involved. ### 1.4 Relationship to content access protocols @@ -75,7 +75,7 @@ An agent cannot reliably declare how it will use content before reading it - a r Events can reference a licence via the `license_ref` field (section 5.2), connecting telemetry to whatever access protocol issued the licence. The telemetry schema does not depend on any specific access protocol. -Discovery protocols and registries - catalogues that describe where content sources are and what they offer, such as agent resource discovery formats - sit upstream of both layers. A catalogue records where a content source is; telemetry records what happened when an agent used it. Content Telemetry is the outcome layer for discovery in the same sense that it is the reporting counterpart to access: it carries no ranking or discovery metadata of its own, and a discovery service that wants outcome signal consumes telemetry like any other party (section 7.3). +Discovery protocols and registries - catalogues that describe where content sources are and what they offer, such as agent resource discovery formats - sit upstream of both layers. A catalogue records where a content source is; telemetry records what happened when an agent used it. Content Telemetry carries no ranking or discovery metadata of its own; a discovery service that wants outcome signal consumes telemetry like any other party (section 7.3). ### 1.5 Conventions @@ -108,6 +108,7 @@ For the purposes of this specification, the following terms apply. | **content owner** | entity that owns or licences content accessed by an AI agent | | **agent operator** | entity running the AI agent that uses content | | **grounding** | content entering the generation model's context, the boundary where content can directly influence output (section 4.3) | +| **recipient** | party a presentation is made perceivable to: the end user, or another person or system receiving the output | | **presentation** | content or a source reference made perceivable on a recipient-facing surface (section 4.3) | | **source role** | classification of the observer reporting a retrieval event: `origin`, `edge`, `index`, or `agent` (section 4.4) | | **privacy level** | data sharing tier controlling which conversation fields are populated: `full`, `summary`, `intent`, or `minimal` (section 5.5) | @@ -164,7 +165,7 @@ The end user sits to the right of the agent and is not shown: they interact with | Telemetry vendor | Intermediary | Telemetry consumer | (consumes only) | | AI agent operator | Agent | Emitter; may self-host a consumer | `agent` | -In the identity and onboarding layer, the three actors are represented by the org types `content_owner`, `platform`, and `agent`; `platform` is the intermediary's identity-layer label. +In the manifest, the three actors are represented by the `roles` values `content_owner`, `platform`, and `agent` (section 8.2); `platform` is the intermediary's label there. ### 4.2 Sessions @@ -311,7 +312,7 @@ Emerging content identification standards - including [ISCC](https://www.iso.org Repositories and mirrors SHOULD use the canonical content identifier from the original source as `content_id` (e.g., the original DOI, ISCC, or publisher-assigned ID) rather than a repository-internal identifier, so that telemetry from multiple hosts of the same content can be correlated without requiring identifier translation. -When correlating events across observers (section 7.2), emitters SHOULD use the canonical URL (from `` or HTTP `Link` header) rather than the URL as fetched, to avoid mismatches caused by redirects, query parameters, or mobile/AMP variants. When both fields are present, `content_url` values MUST match exactly for URL-based correlation. When exact URL matching is unreliable, `content_id` provides a stable alternative. +When correlating events across observers (section 7.2), emitters SHOULD use the canonical URL (from `` or HTTP `Link` header) rather than the URL as fetched, to avoid mismatches caused by redirects, query parameters, or mobile/AMP variants. When two observers each report a `content_url` for the same retrieval, consumers correlate on it only where the values match exactly; where exact URL matching is unreliable, `content_id` provides the stable alternative. Additional content metadata - version, last-modified timestamp, content hash, media type - is carried in event data profiles (section 6) where its relevance varies by event type and source role. @@ -454,7 +455,7 @@ A processor that stores, forwards or transforms a document MUST preserve `terms_ | Type | Description | Expected fields | |------|-------------|-----------------| -| `content_retrieved` | Content fetched from source | `content_url`, `source_role`, `data.media_type` | +| `content_retrieved` | Content fetched from source | `content_url` or `content_id`, `source_role`, `data.media_type` | | `content_grounded` | Content loaded into agent context | `content_url` or `content_id`, `data.scope`, `data.cached` | | `content_cited` | Output explicitly associates source content with an output element | `id`, `output_id`, `content_url` or `content_id`, `data.citation_type` | | `content_presented` | Content or a source reference was made perceivable | `id`, `output_id`, `content_url` or `content_id`, `data.presentation_kind`, `data.presentation_type` | @@ -571,7 +572,6 @@ A conforming **Grounding** emitter MUST satisfy Retrieval requirements and also: - Produce sessions with `schema_version`, `session_id`, `agent_id`, and `started_at` - Emit `content_grounded` events with `data.scope` (schema-enforced; section 6.4) -- Include at least one of `content_url` or `content_id` on every content event - Emit `turn_started` and `turn_completed` events with `privacy_level` - Restrict conversation turn fields to the declared `privacy_level` (section 5.5) @@ -598,7 +598,7 @@ A Citation emitter SHOULD: A conforming **telemetry consumer** MUST: -- Accept documents declaring any `schema_version` with the same major version as the one the consumer implements. `schema_version` is `major.minor` (section 12): v1.0 documents declare `"1.0"`, and the v1.0 schemas accept that value only. Each minor version publishes its own schemas. A consumer implementing 1.y validates a document declaring 1.x, x ≤ y, against the 1.x schemas, and a document declaring a later minor against the latest schemas it implements, tolerating the optional fields that minor added. A v1 consumer MUST reject documents declaring `"0.1"`: v0.1 is a different wire version, not a compatible minor. Conversely, a v0.1 consumer following the preview rule (a 0.x consumer accepts only the exact same minor version, so a 0.1 consumer accepts 0.1 only) rejects documents declaring `"1.0"`. +- Accept documents declaring any `schema_version` with the same major version as the one the consumer implements. `schema_version` is `major.minor` (section 12): v1.0 documents declare `"1.0"`, and the v1.0 schemas accept that value only. Each minor version publishes its own schemas. A consumer implementing 1.y validates a document declaring 1.x, x ≤ y, against the 1.x schemas, and a document declaring a later minor against the latest schemas it implements - relaxing the `schema_version` constant for that document and tolerating the optional fields the later minor added. A v1 consumer MUST reject documents declaring `"0.1"`: v0.1 is a different wire version, not a compatible minor. Conversely, a v0.1 consumer following the preview rule (a 0.x consumer accepts only the exact same minor version, so a 0.1 consumer accepts 0.1 only) rejects documents declaring `"1.0"`. - Tolerate unknown fields without error - Tolerate events from any conformance level - Accept the session-document, standalone-event, and event-batch delivery formats, reconstructing sessions from standalone events and event batches where needed (see section 7.1) @@ -765,7 +765,7 @@ For session-scoped grounding, the number of turns influenced is derivable from t The grounding event marks the point where content enters the generation model's context - the boundary where content can directly influence the model's output text. Content used only for retrieval selection (embedding similarity search, re-ranking, query routing) without entering the generation context is not grounded. -In a pipeline that retrieves 100 articles, generates embeddings for all 100, re-ranks to 10, and places 5 in the generation prompt - the grounding count is 5. The 95 articles used only for selection are retrievals, not groundings. The 10 that survived re-ranking but were not placed in context are also retrievals, not groundings. +In a pipeline that retrieves 100 articles, generates embeddings for all 100, re-ranks to 10, and places 5 in the generation prompt - the grounding count is 5. The other 95 - the 90 eliminated during re-ranking and the 5 that survived it without being placed in context - are retrievals, not groundings. The grounding event is drawn at the same point - entry into the generation context - regardless of agent architecture: @@ -831,8 +831,8 @@ When `content_hash` is absent or does not match any grounding event's hash (for | Field | Type | Description | |-------|------|-------------| -| `presentation_kind` | string | What was made perceivable: `content` or `source_reference` | -| `presentation_type` | string | How it was made perceivable (see below) | +| `presentation_kind` | string | Required. What was made perceivable: `content` or `source_reference` | +| `presentation_type` | string | Required. How it was made perceivable (see below) | | `media_type` | string | Medium made perceivable: `text`, `image`, `video`, `audio` (open vocabulary, see 6.1). Defaults to `text` when absent. | `presentation_kind: content` means source content itself, a bounded excerpt, or a derived representation was made perceivable. It does not claim that the whole source was reproduced. `presentation_kind: source_reference` means a credit, identifier, link, card, or other reference to the source was made perceivable. This distinction is independent of modality: a spoken credit is a source reference; played source audio is content. @@ -857,7 +857,7 @@ A presentation identifies whole content items. Finer-grained portion references Each presentation event MUST have an `id` and `output_id`. When it presents a citation, `citation_id` references that `content_cited` event's `id`, and the two events identify the same content; an uncited presentation omits `citation_id`. Repeated presentations of the same source or output element MUST receive distinct event IDs - event `id` values are unique within a session document. This allows a later `content_engaged.presentation_id` to identify the exact surface occurrence rather than matching only by URL. -When a session includes `content_presented` events but no subsequent `content_engaged` events, the telemetry establishes only that content or a reference was made perceivable and no reported interaction followed. It does not establish human attention. Whether this pattern is meaningful depends on the governing terms. Retrieval remains the only lifecycle stage observable from the CDN edge. +When a session includes `content_presented` events but no subsequent `content_engaged` events, the telemetry establishes only that content or a reference was made perceivable and no reported interaction followed. It does not establish human attention, and whether the pattern is meaningful depends on the governing terms. The pattern is detectable only from agent-reported events: retrieval remains the only lifecycle stage observable from the CDN edge. ### 6.7 Engagement data (`content_engaged`) @@ -865,7 +865,7 @@ When a session includes `content_presented` events but no subsequent `content_en |-------|------|-------------| | `engagement_type` | string | Type of interaction (see below) | -The content URL is identified by the event-level `content_url` field (section 5.2), not duplicated in `data`. Every agent-reported engagement MUST carry `presentation_id`, referencing the exact `content_presented.id` on which the action occurred, and identifies the same content as that presentation (section 5.7.5). Matching on URL alone is insufficient because the same source reference can be presented more than once. A destination-reported engagement carries `ctx_token` on its envelope instead: the destination cannot know the presentation UUID, and the telemetry consumer restores the binding from the token at resolution (section 7.4). +The content URL is identified by the event-level `content_url` field (section 5.2), not duplicated in `data`. Every agent-reported engagement MUST carry `presentation_id`, referencing the exact `content_presented.id` on which the action occurred, and MUST identify the same content as that presentation (section 5.7.5). Matching on URL alone is insufficient because the same source reference can be presented more than once. A destination-reported engagement carries `ctx_token` on its envelope instead: the destination cannot know the presentation UUID, and the telemetry consumer restores the binding from the token at resolution (section 7.4). #### Engagement types @@ -894,8 +894,8 @@ The `data.evidence` field MAY appear on any content event: an array of profile-d | Field | Type | Required | Description | |-------|------|----------|-------------| | `scheme` | string | Yes | Open identifier for the evidence scheme, following the same rules as `content_fingerprint.scheme` (section 6.4) | -| `ref` | string | No | URI of a detached evidence artefact, resolvable independently of the event | -| `digest` | string | No | Digest binding the reference to the artefact's bytes (`sha256:{hex}`) | +| `ref` | string | No | URI of a detached evidence artifact, resolvable independently of the event | +| `digest` | string | No | Digest binding the reference to the artifact's bytes (`sha256:{hex}`) | Core defines the slot and nothing more. It does not interpret entries, register schemes, or assign evidentiary status: an event remains a claim by its emitter (SCOPE.md), and the presence of evidence entries raises no event's status by itself. Which schemes a consumer accepts, and what a verified entry establishes, is consumer trust policy defined in an evidence profile outside core. Consumers MUST tolerate unknown schemes and unknown fields within entries. A detached reference - a `ref` with a `digest` - is admitted deliberately, so evidence can remain independently verifiable after the fact without travelling inline. @@ -964,7 +964,7 @@ An event batch carries the same envelope fields with `"document_type": "event_ba } ``` -Session documents use `"document_type": "session"`. When `document_type` is absent, consumers SHOULD treat the document as a session (for backwards compatibility with pre-0.1 implementations). +Session documents use `"document_type": "session"`. When `document_type` is absent, consumers SHOULD treat the document as a session; the field is optional and early emitters omit it. For origin-side emitters at Retrieval conformance level, `session_id` MAY be omitted when the content owner has no session context. Telemetry consumers correlate these events with agent-reported sessions using the `content_telemetry_id` field. @@ -1209,7 +1209,7 @@ When resolving a manifest from `manifest_ref`, a `content_url` domain, or any ot - **404 or network error.** Treat the participant as unverified. Do not reject telemetry events on this basis alone. - **Invalid JSON or schema validation failure.** Reject the manifest. Treat the participant as unverified. -- **Unknown `schema_version`.** Manifests follow the same rule as telemetry documents (section 5.7.4): accept any `1.x` the consumer implements, validating against that minor's schema, and reject `0.x` manifests. During the v0.x preview period consumers accepted only the exact same minor version. +- **`schema_version`.** Manifests follow the same rule as telemetry documents (section 5.7.4): accept any `1.x`, validating a later minor against the latest manifest schema the consumer implements with the `schema_version` constant relaxed, and reject `0.x` manifests. - **Duplicate `keys[].id`.** Reject the manifest. - **`domains` entry that is not the manifest's host or a subdomain of it.** Reject the manifest as malformed (see 8.6). - **Missing `keys` on a manifest referenced by `manifest_ref`.** Not an error in v1, since signing is informational. @@ -1450,7 +1450,7 @@ using v1 event types or fields. V1 replaces `content_displayed` with `content_presented`; emitters MUST NOT send the old event name on the v1 integration line. Rename `data.display_type` to `data.presentation_type` and add `data.presentation_kind` with either `content` -or `source_reference`. This is an intentional pre-1.0 breaking change: merely +or `source_reference`; both fields are required and schema-enforced (section 6.6). This is an intentional pre-1.0 breaking change: merely renaming the event would preserve the visual-only ambiguity and would not say what crossed the presentation boundary. @@ -1473,8 +1473,10 @@ not migrated as a citation. V1 withdraws `ip_hash` from the edge and origin retrieval profiles (section 9.1). Emitters remove the field and MUST NOT populate it; `asn`, `asn_org` and `country` -remain. V1 also requires `source_role` on every `content_retrieved` event -(section 5.7.1); preview emitters that omitted it add the role they report under. +remain. V1 also restates `source_role` on every `content_retrieved` event as an +application-layer rule binding all emitters (sections 5.2.2, 5.7.5), not only a +Retrieval-conformance requirement; emitters that omitted it add the role they +report under. V1 renames the retrieval profile's `bot_category` field to `purpose` and defines it as an open enum classifying the access rather than the bot: the v0.1 values @@ -1509,7 +1511,9 @@ from a token to the presentation it was minted for is issuer state: v0.1 defined no `presentation_id`, and v1 never places one in a URL; a destination reports the token, and the consumer restores the binding at resolution. -V1 tightens occurrence boundaries (section 4.3). Each core event now has a stated occurrence and cardinality: retrieval per completed fetch (a cache serve is not a retrieval), grounding per distinct content item per declared scope (chunk-level events deduplicate to one occurrence by content identity), citation per source-to-element association, presentation per rendering occurrence, engagement per observed action. Preview emitters that emitted per chunk, per passage, or re-emitted `content_retrieved` on cache serves remain schema-valid but SHOULD re-map to the stated boundaries; consumers comparing preview and v1 volumes should expect counts to shift where emitters previously chose finer or coarser units. Coverage becomes an explicit declaration (section 5.7.6) rather than an implication of conformance level. Session-scoped extension metadata belongs in the session-level `data` container (section 5.1.3); custom top-level siblings of `events`, accepted by the preview schema, are undefined. +V1 tightens occurrence boundaries (section 4.3). Each core event now has a stated occurrence and cardinality: retrieval per completed fetch (a cache serve is not a retrieval), grounding per distinct content item per declared scope (chunk-level events deduplicate to one occurrence by content identity), citation per source-to-element association, presentation per rendering occurrence, engagement per observed action. Preview emitters that emitted per chunk, per passage, or re-emitted `content_retrieved` on cache serves remain schema-valid but SHOULD re-map to the stated boundaries; consumers comparing preview and v1 volumes should expect counts to shift where emitters previously chose finer or coarser units. Coverage becomes an explicit declaration (section 5.7.6) rather than an implication of conformance level. Session-scoped extension metadata belongs in the session-level `data` container (section 5.1.3); custom top-level siblings of `events` remain schema-valid but are undefined, and consumers need not preserve them. + +### 12.2 Version numbering Version numbers are `major.minor`, and a document declares the version it was produced under in `schema_version`. From 1.0 onward: @@ -1527,7 +1531,7 @@ See `telemetry-session.json` for the formal JSON Schema definition. ### B.1 User-to-agent session with grounding -A user asks a shopping assistant to compare noise-cancelling headphones. The agent retrieves a review, grounds it, cites it, and the user clicks through. This demonstrates the full funnel from retrieval to engagement. +A user asks a shopping assistant to compare noise-cancelling headphones. The agent retrieves a review, grounds it, cites it, presents the link, and the user clicks through. This demonstrates the full funnel from retrieval to engagement. ```json { diff --git a/manifest.json b/manifest.json index f418b8e..d61a7d2 100644 --- a/manifest.json +++ b/manifest.json @@ -55,7 +55,7 @@ "type": { "type": "string", "const": "Ed25519", - "description": "Key type. v0.1: Ed25519. (Section 8.4)" + "description": "Key type. v1 defines Ed25519 only. (Section 8.4)" }, "publicKey": { "type": "string", @@ -68,7 +68,7 @@ } } }, - "description": "Public keys for signing telemetry events. Per-event signing is informational in v0.1. (Section 8.4)" + "description": "Public keys for signing telemetry events. Per-event signing is informational in v1. (Section 8.4)" }, "telemetry": { "type": "object", diff --git a/telemetry-session.json b/telemetry-session.json index c3aed4f..d9e421f 100644 --- a/telemetry-session.json +++ b/telemetry-session.json @@ -113,7 +113,7 @@ "id": { "type": "string", "format": "uuid", - "description": "Unique event identifier; distinct within a session document (section 6.7)" + "description": "Unique event identifier; distinct within a session document (sections 5.7.5, 6.6)" }, "type": { "$ref": "#/$defs/EventType" @@ -374,7 +374,7 @@ }, "model_id": { "type": ["string", "null"], - "description": "Model identifier (e.g., 'claude-4-sonnet')" + "description": "Model identifier (e.g., 'vendor-model-v3')" }, "ad_rendered": { "type": ["boolean", "null"],