Skip to content

Commit 9afb96f

Browse files
committed
docs: substantive CRG C annotation (EXPLAINME.adoc)
1 parent 6161197 commit 9afb96f

1 file changed

Lines changed: 137 additions & 11 deletions

File tree

EXPLAINME.adoc

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,160 @@
11
// SPDX-License-Identifier: PMPL-1.0-or-later
2-
= RSR Template Repository — Show Me The Receipts
2+
= a2ml-rs — Show Me The Receipts
3+
Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
34
:toc:
45
:icons: font
56

67
The README makes claims. This file backs them up.
78

9+
== A2ML Is a Parser and Renderer for Attested Markup Language
10+
811
[quote, README]
912
____
10-
The AI reads the manifest, asks you a few questions, and handles everything.
13+
Parser and renderer for A2ML (Attested Markup Language). A2ML is a lightweight
14+
markup format designed for AI-agent communication that carries built-in
15+
attestation metadata, enabling provenance tracking and trust-level annotations
16+
on document content.
17+
____
18+
19+
A2ML (Attested Markup Language) extends a Markdown-like surface syntax with
20+
two first-class constructs: `@directives` (machine-readable metadata prefixed
21+
with `@`) and `!attest` blocks that record identity, role, and trust-level on
22+
any piece of content. The parser in `src/parser.rs` is a line-by-line state
23+
machine: it accumulates paragraph text in a buffer, recognises headings,
24+
directives, attestation lines, fenced code blocks, block quotes, thematic
25+
breaks, and ordered/unordered lists, then flushes each recognised structure
26+
into a `Vec<Block>`. The renderer in `src/renderer.rs` serialises the same
27+
`Document` AST back to canonical A2ML text, making round-trips deterministic.
28+
29+
**Caveat:** The MVP parser is single-pass and line-oriented — it does not
30+
handle nested block structures beyond one level of block-quote recursion.
31+
Multi-line directives (as used in the Haskell variant with `@name: ... @end`
32+
blocks) are not yet supported; directives here are single-line `@name value`
33+
pairs only. No HTML or PDF output is built in — use `pandoc-a2ml` (the Lua
34+
reader in `hyperpolymath/pandoc-a2ml`) for format conversion.
35+
36+
- Implementation: `src/parser.rs` (parse, parse_file), `src/renderer.rs` (render)
37+
- Core types: `src/types.rs` (Document, Block, Inline, Directive, Attestation, TrustLevel, Manifest)
38+
- Error surface: `src/error.rs` (A2mlError::ParseError, A2mlError::Io, A2mlError::RenderError)
39+
- Learn more: https://docs.rs/a2ml (forthcoming), https://github.com/hyperpolymath/a2ml
40+
41+
== Attestation Chain Is a First-Class Type
42+
43+
[quote, src/types.rs]
44+
____
45+
An A2ML document consists of a sequence of Block elements, each of which may
46+
contain Inline content. Directive blocks provide machine-readable metadata,
47+
and Attestation records capture the provenance chain for AI-generated or
48+
human-reviewed content.
49+
____
50+
51+
The `TrustLevel` enum defines four ordered levels: `Unverified` → `Automated`
52+
→ `Reviewed` → `Verified`. Attestations carry `identity` (person or agent
53+
name), `role` (e.g. `"author"` or `"agent"`), `trust_level`, an optional
54+
ISO-8601 timestamp, and a free-form note. The `Manifest` struct is a
55+
convenience aggregate that extracts the `@version` directive and all
56+
attestations from a `Document` into a single value for programmatic inspection.
57+
The `parser.rs` attestation parser (`parse_attestation`) requires `identity`,
58+
`role`, and `trust` fields; unknown keys are silently skipped for
59+
forward-compatibility.
60+
61+
**Caveat:** Attestations are syntactic declarations, not cryptographic
62+
signatures. There is no signature verification or public-key infrastructure
63+
here — that layer belongs in `cookie-rebound` and the broader Groove protocol
64+
stack. `TrustLevel::Verified` means _claimed_ verified, not proven.
65+
66+
- Implementation: `src/types.rs:167–293` (Attestation, TrustLevel, Manifest)
67+
- Parser path: `src/parser.rs:398–445` (parse_attestation)
68+
- Learn more: https://www.rfc-editor.org/rfc/rfc9068 (JWT for comparison)
69+
70+
== Safe Rust Without unsafe_code
71+
72+
[quote, src/lib.rs]
73+
____
74+
#![forbid(unsafe_code)]
75+
____
76+
77+
The crate gate is `#![forbid(unsafe_code)]` — the compiler rejects any
78+
`unsafe` block at the crate root. Dependencies are minimal: `serde`/`serde_derive`
79+
for JSON serialisation, `thiserror` for ergonomic error types, and `criterion`
80+
for benchmarks only. There are no proc-macro or build-script dependencies that
81+
could introduce hidden unsafe paths.
82+
83+
**Caveat:** Transitive dependencies (serde internals, thiserror) are not under
84+
the same `forbid` gate. Use `cargo-geiger` or `panic-attacker` to audit the
85+
full dependency tree if deploying in a security-sensitive context.
86+
87+
- Crate root: `src/lib.rs:1` (#![forbid(unsafe_code)])
88+
- Learn more: https://doc.rust-lang.org/reference/unsafe-blocks.html
89+
90+
== MPL-2.0 Fallback for crates.io
91+
92+
[quote, Cargo.toml]
93+
____
94+
license = "MPL-2.0"
95+
# (PMPL-1.0-or-later preferred; MPL-2.0 required for crates.io)
1196
____
1297

13-
== Technology Choices
98+
crates.io requires an OSI-approved SPDX identifier; PMPL-1.0-or-later is not
99+
yet recognised by OSI. Every source file carries the dual comment:
100+
`// SPDX-License-Identifier: MPL-2.0 // (PMPL-1.0-or-later preferred; ...)`.
101+
This follows the project-wide fallback policy documented in CLAUDE.md.
102+
103+
**Caveat:** The published crate on crates.io is effectively MPL-2.0. Any
104+
fork or redistribution outside the crates.io ecosystem should honour
105+
PMPL-1.0-or-later where the platform permits it.
106+
107+
- License file: `LICENSE` (PMPL-1.0-or-later text), `LICENSE-MPL-2.0`
108+
- Learn more: https://github.com/hyperpolymath/palimpsest-license
109+
110+
== Dogfooded Across The Account
14111

15112
[cols="1,2"]
16113
|===
17-
| Technology | Learn More
114+
| Technology | Also Used In
115+
116+
| **A2ML format** | https://github.com/hyperpolymath/a2ml-haskell[a2ml-haskell] (Haskell binding), https://github.com/hyperpolymath/pandoc-a2ml[pandoc-a2ml] (Lua reader), https://github.com/hyperpolymath/tree-sitter-a2ml[tree-sitter-a2ml] (grammar)
117+
118+
| **Rust + thiserror** | https://github.com/hyperpolymath/panic-attacker[panic-attacker], https://github.com/hyperpolymath/patch-bridge[patch-bridge], https://github.com/hyperpolymath/protocol-squisher[protocol-squisher]
18119

19-
| **Rust** | https://www.rust-lang.org
120+
| **Criterion benchmarks** | https://github.com/hyperpolymath/patch-bridge[patch-bridge] (bridge_bench.rs), https://github.com/hyperpolymath/a2ml-haskell[a2ml-haskell] (a2ml-bench)
121+
122+
| **SPDX MPL-2.0 fallback** | https://github.com/hyperpolymath/a2ml-haskell[a2ml-haskell] (Hackage policy)
123+
124+
| **0-AI-MANIFEST.a2ml gatekeeper** | All RSR repositories — this crate is itself an implementation of the format it parses
20125
|===
21126

22127
== File Map
23128

24129
[cols="1,2"]
25130
|===
26-
| Path | What's There
131+
| Path | Proves
27132

28-
| `src/` | Source code
29-
| `test(s)/` | Test suite
30-
|===
133+
| `src/lib.rs` | Crate root: module declarations, re-exports, `#![forbid(unsafe_code)]` gate
134+
135+
| `src/types.rs` | Core AST: `Document`, `Block`, `Inline`, `Directive`, `Attestation`, `TrustLevel`, `Manifest` — the canonical data model
136+
137+
| `src/parser.rs` | Line-by-line parser: `parse(&str) -> Result<Document>`, `parse_file(Path) -> Result<Document>`, internal `ParserState`, all block and inline parsers
31138

32-
== Questions?
139+
| `src/renderer.rs` | Canonical serialiser: `render(&Document) -> Result<String>`, block/inline/directive/attestation rendering
33140

34-
Open an issue or reach out directly — happy to explain anything in more detail.
141+
| `src/error.rs` | `A2mlError` enum: `ParseError { line, col, message }`, `Io(std::io::Error)`, `RenderError`
142+
143+
| `Cargo.toml` | Crate metadata: name=`a2ml`, version=`0.1.0`, keywords, categories, dependency pinning
144+
145+
| `tests/e2e_test.rs` | End-to-end parse→render→re-parse round-trip tests
146+
147+
| `tests/property_test.rs` | Property-based tests (QuickCheck-style via proptest)
148+
149+
| `tests/aspect_test.rs` | Cross-cutting concern tests (error paths, edge cases)
150+
151+
| `benches/a2ml_bench.rs` | Criterion benchmarks for parse and render hot paths
152+
153+
| `tests/fuzz/` | Fuzz corpus placeholder (AFL/cargo-fuzz integration target)
154+
155+
| `0-AI-MANIFEST.a2ml` | AI session gatekeeper — read first before modifying any file
156+
157+
| `.machine_readable/` | A2ML state files: STATE.a2ml, ECOSYSTEM.a2ml, META.a2ml, AGENTIC.a2ml
158+
159+
| `verification/` | Formal verification artefacts (Idris2 proofs, pending)
160+
|===

0 commit comments

Comments
 (0)