Reporting: from a verified bundle to a page
Seams ④ Result to ⑤ View. Build: a page drawn only after the bundle verifies. Conform to: draft-mih-zhang-agent-disclosure-bundle-00.
A report is a presentation of an evidence file for one reader. The page is drawn only after the file verifies, by a module the reader's viewer selects from declared manifests, in words that live outside the evidence, so rewording or translating a report never moves an evidence identifier.
1What it is
Reporting turns one verified evidence file into a page for one reader: verification runs once, its result is frozen, and a registry picks the one presentation module whose declared manifest matches the file.
The module builds a model from verified content only and draws it into a common shell that makes no network request and prints, as an offline file, a fragment link, an embedded view or a static rendering that runs no script; three separate depth levels are designed.
Words split two ways: what someone said, saw or approved is bound in the record as a commitment, while headings and labels live in a hash-pinned wording pack, so the same evidence can be reworded or translated without a single evidence identifier moving.
2Design choices
VerifiedBundleContext that every module reads.forbids; two specific modules that both match are an error, checked at registration and at resolution.sha256-jcs-nonce256 commitment, or a separately sealed text record.report/v1 row model. (contract §7.1, §7.2)aac.wording-pack/v0), one locale per pack, referenced by wording_sha256 over its exact bytes; the builder refuses a pack that does not hash to it, and a renderer falls back to the core's own labels.presentation_api and runtime_min; a viewer that cannot honour them refuses the module and names it on the page.3What it shows / what it does not
Shows
- Whether the file verified, before anything else is drawn; on failure, which checks failed.
- Which module drew the page, and that its script is the one the builder pinned (CSP hash).
- Every extension in the file, each with its integrity and whether this viewer interpreted it; an unknown one reads “meaning not interpreted”, never hidden.
- Evidentiary words only after their commitment recomputes; without an opening, that the text is committed and not opened.
- The same content and verify state in every packaging supported for one file and one audience.
Does not show
- That the records are true, or that an answer was right: that is judgment, kept on its own step (b9).
- That a module's layout is a fair reading of the evidence: the pin shows which code ran, not that it is correct.
- Anything from the static page by itself: it runs no script and says it is not self-verifying.
- Anything from a picture or a text summary of the same model: those are presentation, never something a reader can check.
- Who holds a signing key in the real world.
4Example
Two example manifests from the spec repository. Both match the same profile; one forbids the composition extension and the other requires it, so no bundle matches both. Neither carries a word of display text.
{
"spec_version": "aac.presentation-manifest/v0",
"id": "org.example.unilateral/v0",
"presentation_api": "aac.presentation-api/v0",
"runtime_min": "0.1.0",
"trust_class": "trusted-executable",
"requires": {
"bundle_kind": "evidence-bundle/v2",
"profiles": ["spec_version:org.example.exchange/v0"]
},
"forbids": { "extensions": ["composed/v1"] },
"audiences": ["*"],
"formats": ["html", "fragment", "embedded"],
"fallback": false,
"priority": 1,
"executable": {
"carrier": "module-slot",
"script_sha256": "1f0e3dad99908345f7439f8ffabdffc41f0e3dad99908345f7439f8ffabdffc4"
}
}
Source: agent-action-capsule:schemas/examples/presentation-manifest-v0/example-unilateral.json @ 2ef8aeb49e2334e24c404bd62d3fdb161770873c; its pair example-composition-aware.json has the same requires plus "extensions": {"required": ["composed/v1"]}.
| Name | Type | Meaning |
|---|---|---|
| id | string | The module id, <dotted name>/v<major>. The aac. prefix is reserved for modules the spec repository ships; anyone else uses their own name. |
| presentation_api | string | The module-to-runtime interface it is written against. A viewer that does not implement it refuses the module out loud. |
| runtime_min | MAJOR.MINOR.PATCH | The lowest runtime version it needs; versioned independently of the id and of the interface. |
| trust_class | enum | trusted-executable (a pinned script) or declarative (fields and a wording pack, no code). |
| requires | object | Bundle kind (equality), profile tokens <key>:<value>, and extensions that must be engaged. |
| forbids | object | Profiles or extensions that must be absent: the only way one specific module excludes another. |
| audiences / formats | arrays | Who the page is for ("*" for all) and which packagings the module supports. |
| fallback / priority | bool / int | priority only ranks a specific module above a fallback; it never settles a tie between two specific modules. |
| executable | object | Where the script lives (module-slot) and its script_sha256; the page's CSP lists that digest. |
The words come from a separate pack whose exact bytes hash to the wording_sha256 a declarative manifest names (0a04a729bf29caecda23cae6b5faa320f8aabc495458e99180150059e63c3730 for this one):
{ "wording_pack_version": "aac.wording-pack/v0",
"id": "org.example.rules-table.wording/v0",
"locale": "en",
"entries": {
"module.title": "Rules table",
"page.title": "Rules comparison",
"heading.l0": "What the comparison found",
"state.unknown": "Not established: no finding either way",
… } }
Source: agent-action-capsule:schemas/examples/presentation-manifest-v0/example-wording-pack.json and example-declarative-rules.json @ 2ef8aeb49e2334e24c404bd62d3fdb161770873c (entries trimmed).
The test of an open presentation layer
An outside developer, with only the open pieces, writes a module such as acme.monthly-risk-report/v1: a manifest under their own name, a script pinned by its hash, a wording pack. The builder puts it in a page that verifies offline, and nobody has to add a case to the viewer for it. Today that path exists for a pinned script: capsule-viewer's builder tests build pages from org.example.* module-slot modules, and refuse one whose interface or runtime the page cannot honour. The declarative path (no code at all) is designed, not built.
5Status
| Piece | Status | Evidence |
|---|---|---|
| Verify core | live | agent-action-capsule ts/src/bundle.ts, ts/src/verify.ts @ 2ef8aeb49e2334e24c404bd62d3fdb161770873c; released in @action-state-group/agent-action-capsule 0.3.0 on npm (tag ts/v0.3.0, 40f1567fee15f677debdfb56c4c39ba884880dce). |
| Frozen verified context | live | #202; ts/test/verified-bundle-context.test.ts; in ts 0.3.0. |
| “Unable to verify” distinct from failed | live | #226; UNABLE_TO_VERIFY_LINES in ts/src/evidence-graph-view.ts; in ts 0.3.0. |
| Extension rows: integrity + interpretation | live | #205; in ts 0.3.0. The Go, Python and Rust verifiers render no page and still report every extension uninterpreted (contract Appendix C.6). |
| Registry, ambiguity error, refusal | live | TypeScript #207 (ts/src/presentation-registry.ts, ts 0.3.0); Go #217 (go/presentation/, tag go/v0.10.0 626074f631eb20454aef0b3a0f67320ddaf66119); both run the shared vectors/presentation-resolution/. |
| Generic composition view | live | #208 (ts/src/composed-view.ts); in ts 0.3.0. |
| Shell: slots, base CSS, per-page CSP | live | Built in #203 and #214; moved to capsule-viewer (Apache-2.0 AND BSD-3-Clause) in capsule-viewer#33 and removed from the spec repository in #302; released as @action-state-group/capsule-viewer 0.1.0 on npm (tag ts/v0.1.0, 5c9042578de2eccccf4a93b6d820945ce1208e2e). |
| Builder: three formats + static rendering, availability, wording-pack hash check | live | Built in #209 and #216; now capsule-viewer ts/src/presentation-builder.ts (availablePackagings, checkWordingPack) in capsule-viewer 0.1.0; fragment codec and mount() stay in the spec repository (ts/src/presentation-fragment.ts, ts/src/presentation-mount.ts). |
| Contract, manifest schema, examples | live (design spec) | spec/presentation-contract-v0.md (#206, revision 1 #215), schemas/presentation-manifest-v0.json and its checker @ 2ef8aeb. A design specification in the repository, not an Internet-Draft. |
| Module services | built: 3 of 8 | details, badge, disclosure are built; section, citation, format.*, countersigner and wording are designed, not built (contract Appendix C.9). |
| Separate L0 / L1 / L2 regions | designed | The reference runtime hands a module one element for all three today (contract Appendix C.10). |
| Declarative renderer (no-code modules) | designed | Not built: no declarative module can be rendered by the reference runtime today (contract Appendix C.9). The example manifests and pack exist as schema fixtures. |
| An outside developer's module | planned | The pinned-script path is exercised by capsule-viewer ts/test/presentation-builder.test.ts @ 204e07a87cae17886b87f1324a5040a4aec6b8bf with org.example.* modules. No module from outside the repositories' authors was checked. |
6Specs
- Design spec Presentation Contract v0 — module interface, manifest, resolution, trust classes, text-binding rule, invariants, depth levels. In the agent-action-capsule repository; not an Internet-Draft.
- Design spec Presentation Builder v0 — the one builder, its three formats and the static rendering.
- Internet-Draft draft-mih-zhang-agent-disclosure-bundle-00 — the Evidence Bundle being presented, what “verified” means for it, and its permalink codec.
- Internet-Draft draft-mih-scitt-agent-action-capsule-05 — the records inside the bundle and their
capsule_id. - RFC RFC 8785 — JSON Canonicalization Scheme: the form commitments and wording packs are hashed in.
- Code agent-action-capsule — verify core, context, registry, built-in views, resolution vectors.
- Code capsule-viewer — the shell and the builder.
7What you need before the next step
- Reports that are drawn only from a verified, frozen context, and a failure path that shows the refusal and nothing else.
- Your report types written as modules with manifests under your own name, selected by the registry, never by your code inspecting the file.
- Every word a reader may rely on bound in a record; every other word in a hash-pinned wording pack outside the evidence.
- A page that makes no request and runs only pinned scripts, so a reader can open it offline from an email or a folder.
- Reports are reads over sealed records, not new evidence. The next step does the same over time: history, read back from the records and fed into the next decision.