open-standards/aac/SPEC.md
Transaction Science ba1212361f Add aac, map, sandbox standards; catalog the standards family
Commit the previously-untracked standard directories and catalog them in the
root README alongside proof:

- aac/    — communication cargo class: portable boards + a ten-level
            offline-first cascade (Apache-2.0 code / CC-BY-4.0 spec).
- map/    — geospatial cargo class: range-requestable signed tilesets +
            an F0–F4 fidelity cascade (Apache-2.0 code / CC-BY-4.0 spec).
- sandbox/— isolated, metered, attested execution across the heterogeneous
            compute fabric (Apache-2.0 code / CC-BY-4.0 spec).
- jouleclaw-otel-authz, jouleclaw-trust — new jouleclaw reference crates.

Root README now lists aac, map, sandbox, and proof in the catalog, the tree,
and the contribution guide.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-07 17:04:36 -04:00

151 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AAC — Specification
**Version 0.1.0 (draft) · Status: draft · Licence: CC-BY-4.0**
This document specifies the AAC open standard: the data model for a portable communication board, the access-method abstraction, the energy-tiered communication cascade, canonical serialization, the interchange format, and the receipt. The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHALL**, **SHOULD**, **SHOULD NOT**, **MAY**, and **OPTIONAL** are to be interpreted as described in RFC 2119.
The Rust reference implementation in [`aac-rs/`](aac-rs/) is normative-by-example: where this prose and the reference types disagree, that is a defect to be reconciled, not a license to diverge.
---
## §1. Scope and terms
AAC (augmentative and alternative communication) is technology that lets a person who cannot rely on speech compose and produce utterances. This standard specifies how a **board** — a person's communication surface and the customization invested in it — is represented, accessed, and exchanged so that it is portable across implementations and devices, operable offline, and never gated behind payment.
- **Board** — a surface holding cells, of a given `BoardType` (`Grid | VisualScene | Keyboard | Hybrid | QuickAccess`).
- **Cell** — a single selectable target on a board, at a fixed grid position, with content and an action.
- **Utterance** — the message a user composes by selecting cells.
- **Access method** — the physical channel by which a user selects (`DirectTouch | EyeGaze | HeadTracking | SwitchScan{switches} | Joystick | Bci | PartialVoice | Pointer`).
- **Client** — software that opens, renders, drives, and speaks a board.
- **Cascade level** — one of ten tiers (L0–L9) through which a communication operation is resolved.
This standard does **not** specify rendering pixels, a UI toolkit, a TTS engine, or symbol artwork. It specifies the data and the invariants that make a voice portable.
---
## §2. The board data model
A board **MUST** be representable as the following structure (field names are normative; the reference type is `aac_core::Board`):
- `id` — a `BoardId` (UUID), stable for the life of the board.
- `name` — display string.
- `board_type` — one of the `BoardType` variants.
- `layout` — a `GridLayout { rows: u16, cols: u16 }`.
- `cells` — a list of `Cell`.
A **cell** **MUST** carry:
- `id` — a `CellId` (UUID).
- `position` — a `GridPosition { row: u16, col: u16 }`, 0-indexed.
- `content` — one of: `Symbol { symbol_id, label }`, `Text(String)`, `Photo { image_ref, label }`, or `Blank`.
- `action` — one of: `Speak(text)`, `Navigate(BoardId)`, `Modifier(GrammarModifier)`, `Backspace`, `Clear`, `Predict`, `SpeakAll`, `Buffer(text)`.
- `style` — colors and optional font size; a client **MAY** override style for accessibility (§5) but **MUST NOT** alter `position`.
- `frequency` — usage count, monotonically non-decreasing.
- `locked` — whether the cell is protected from structural edits.
Boards form a **graph**: a `Navigate` action edges from one board to another. The graph is the source of truth; a grid layout is one projection of it. A `Blank` cell is meaningful — it reserves a position to preserve the motor grid (§3) and **MUST NOT** be elided on round-trip.
---
## §3. Motor stability (normative invariant)
A user's motor plan — the learned muscle memory of where each word lives — is the single most valuable property of a configured board. Therefore:
1. A cell's `position` **MUST NOT** change once assigned, for the life of that cell, except by an explicit user/editor edit to an `unlocked` cell. Prediction, context, frequency, language switching, and any L3+ enrichment **MUST NOT** move a cell.
2. A client **MUST NOT** reflow, resort, or auto-arrange cells on a board whose cells are `locked`.
3. Hiding a word for teaching (progressive disclosure) **MUST** be done by rendering its cell as visually inactive **in place** — never by removing it and collapsing the grid.
4. Two openings of the same board on the same or different conforming clients **MUST** present identical cell positions.
An implementation that rearranges a locked board is non-conformant regardless of any other quality.
---
## §4. Symbols
Cell `Symbol` content references a symbol by `symbol_id` and `SymbolSource`, **not** by embedded pixels. A board therefore travels as a small, text-like document; artwork is resolved by the client from a symbol library. A client **MUST** preserve the `symbol_id` and `label` on round-trip even if it cannot render the referenced artwork, and **SHOULD** fall back to rendering the `label` text when artwork is unavailable. This keeps a board legible across implementations that ship different symbol sets.
---
## §5. Access model
Every access method is a first-class input. A board **MAY** be driven by any method; the method and its tuning travel with the user's profile, not the board.
- **AccessMethod** — as enumerated in §1. `SwitchScan { switches }` carries the switch count (1, 2, or more).
- **MotorProfile** — `fine_motor`, `sustained_press`, `tremor_level`, `min_target_mm`, optional `max_reach_mm`, `preferred_side`. A client **SHOULD** adapt target size and timing from this profile, and **MUST NOT** require a smaller target than `min_target_mm`.
Timing-based methods are normative in their own right:
1. **Switch scanning** — a conforming scanner **MUST** support row-column, linear, and group scan patterns, a configurable scan rate, and configurable acceptance/timing. Adaptive rate, where enabled, **MUST** stay within explicit `[min, max]` bounds.
2. **Dwell / eye-gaze** — selection by sustained gaze **MUST** use a configurable dwell time with visible progress feedback, and **SHOULD** adapt to fatigue within bounds.
3. No access method **MAY** be a precondition for opening or reading a board; a board authored for eye-gaze **MUST** still open under touch or switch.
---
## §6. The cascade
A communication operation **MUST** be resolved through the lowest cascade level that can satisfy it. The ten levels and their order are normative:
| Level | Name | Order-of-magnitude energy |
|-------|------|---------------------------|
| L0 | `CacheHit` | ~1 µJ |
| L1 | `SymbolLookup` | ~10 µJ |
| L2 | `LocalPredict` | ~100 µJ |
| L3 | `ContextPredict` | ~1 mJ |
| L4 | `SemanticExpand` | ~10 mJ |
| L5 | `ConversationAi` | ~100 mJ |
| L6 | `GenerativeComm` | ~1 J |
| L7 | `VoiceClone` | ~5 J |
| L8 | `MultimodalGen` | ~10 J |
| L9 | `AdaptiveModel` | ~15 J |
**§6.1 Energy monotonicity.** The estimated energy of level `Lₙ` **MUST** be strictly greater than that of `Lₙ₋₁`. (Conformance suite C2.)
**§6.2 Offline invariant.** Levels L0, L1, and L2 — and **only** these — **MUST** be offline-capable. A conforming client **MUST** serve every L0–L2 operation with no network access, and **MUST NOT** make any L0–L2 operation contingent on connectivity. (Conformance suite C3.) The practical consequence is normative: a network failure **MUST NOT** prevent a user from selecting cells, looking up symbols, or completing words.
**§6.3 Free at every level.** No cascade level **MAY** be gated behind payment, quota, balance, or subscription at the protocol layer. An implementation **MUST NOT** refuse, degrade, or rate-limit a communication operation on the basis of billing state. Hosted enrichment services (L3+) **MAY** be operated commercially, but a conforming client **MUST** remain fully functional through L2 with no account.
**§6.4 Enrichment is optional.** L3 and above add intelligence (context, sentence construction, voice cloning, symbol generation, model adaptation). They **MUST** be reached only when a lower level cannot close the request, and their absence **MUST NOT** degrade L0–L2 behavior.
---
## §7. Canonical serialization and content addressing
A board **MUST** have a canonical serialization. JSON is the interchange encoding; a canonical form (sorted keys, normalized number forms) **MUST** round-trip byte-identically through a conforming serializer. A board's content identity **MAY** be expressed as a content address (e.g. BLAKE3) over its canonical bytes; two boards with equal canonical bytes are the same board.
---
## §8. Interchange (ingest)
A board **MUST** export to the canonical form of §7 and **MUST** be re-importable from it without loss of cell positions, content, actions, or symbol references.
A conforming engine **SHOULD** additionally **ingest** the open board interchange format and common community exports. Ingestion is one-directional and additive: it reads existing work into the substrate so a user does not start over. On ingest:
- Cell positions present in the source **MUST** be preserved (§3); positions absent from the source **MUST** be assigned deterministically (row-major fill) and then fixed.
- Unsupported or unknown fields **MUST** be reported as non-fatal warnings, never silently dropped where they affect meaning.
- A format the engine cannot yet read **MUST** fail explicitly (a named "format not yet supported" error), never partially and silently.
---
## §9. The receipt
Every operation **MAY** report a two-part energy cost (`measured + estimated`) in microjoules, with an honest provenance tag indicating whether a reading came from hardware instrumentation, a model, or an estimator. The receipt exists for **transparency only**. An implementation **MUST NOT** convert a receipt into a charge, a quota, or a gate. "This session used 3.2 mJ" is a fact shown to the user; it is never a bill.
---
## §10. Conformance
An implementation is conformant if it:
1. Round-trips the published board vectors (§7) byte-identically.
2. Preserves the motor-stability invariant (§3) across open/edit/save.
3. Routes operations to the specified cascade levels and satisfies energy monotonicity (§6.1).
4. Serves exactly L0–L2 offline (§6.2) and gates no level behind billing (§6.3).
5. Ingests the interchange format without losing positions, content, or actions (§8).
The [`aac-conformance`](aac-rs/crates/aac-conformance) harness checks the cascade routing table (C1), energy monotonicity (C2), the offline invariant (C3), and wire round-trips (C4). Any FAIL makes the run non-zero.
---
## §11. Non-claims
This standard and its reference implementation are **not** a medical device and have **not** been certified as a speech-generating device (SGD) for insurance or Medicaid funding. They make no clinical claim. Selection of an access method, vocabulary, and communication approach for a given person is a clinical decision for a qualified speech-language pathologist and the user's team. The standard provides the portable substrate; it does not replace assessment, training, or support.