For someone who looks, points or touches, only their own switches count for the way out: a hand resting on a laptop's keyboard never does. While the way out waits to be kept, looking (the camera) and pointing go on, so Go back now can be chosen as before; it offers no Keep button, and is kept only by a press of the held switch after it came up, past the release time (a bounce keeps nothing). With no change already waiting, it brings times that lock nobody out (SPEC §5.7 item 8). The scan's cues are provisional too (item 6): someone who scans by ear cannot scan without them. The natural voice counts as speaking only while its audio runs, so a system interruption does not silence the cues; what it held is stopped. While Help's message shows, its Done is scanned as the message bar. For someone who hears the scan, it waits while their words are said. A waiting change is not put back over what another version of the app changed meanwhile. Co-Authored-By: Claude Opus 5.5 <[email protected]>
318 lines
40 KiB
Markdown
318 lines
40 KiB
Markdown
# AAC — Specification
|
||
|
||
**Version 0.2.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.
|
||
|
||
*(Proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance.)* A reader **MUST** keep every field of a board or a cell that it does not recognize and write it back unchanged when it saves the board. A board saved by a newer client then loses nothing when an older client opens and saves it.
|
||
|
||
---
|
||
|
||
## §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.
|
||
|
||
### §4.1 Language honesty
|
||
|
||
A board travels between languages as a graph edge (a translation of each label), but a word list translated from one language is not another language's core vocabulary: the words people use most differ from language to language. Therefore:
|
||
|
||
1. Every language a client offers **MUST** state how its core vocabulary was obtained, as a `CoreStatus`: `ValidatedNativeCorpus` (a published core list derived from speakers of that language), `StakeholderValidated` (nominated and rated by its speakers and communication partners), `PrimesOnly` (a provisional seed from semantic primes and frequency lists), or `GlossOnly` (glosses of another language's core list).
|
||
2. A language record without a `CoreStatus` **MUST** be read as `GlossOnly`.
|
||
3. A client **MUST NOT** present `GlossOnly` vocabulary as that language's core vocabulary, and **SHOULD** show each language's status where the person chooses a language.
|
||
|
||
The reference ships 45 languages: English is `ValidatedNativeCorpus`; the other 44 are `GlossOnly` until their speakers validate their own. (Conformance C7.)
|
||
|
||
### §4.2 What a suggestion may propose *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
A client **MAY** suggest words — a next word, a sentence start, the completion of a word being typed — from a language model and from what the person has said. A model built from published text (subtitles, news, the web) proposes whatever that text holds, including rude, sexual and violent words, and a word proposed unprompted is a word put in the person's mouth. Therefore:
|
||
|
||
1. A client **MUST** propose only words from the person's vocabulary — the words of the boards they use, in their language — and words they have said themselves, unless the person, or someone acting with them, has chosen to include a language's whole word list.
|
||
2. The whole word list **MUST** be off unless chosen, and a client **MUST** say where it comes from before it is chosen.
|
||
3. A model **MAY** rank the permitted words whatever the choice; ranking a word is not proposing it. Letter predictions (which keys to order or highlight) **MAY** use the whole word list, because a letter proposes no word.
|
||
4. None of this limits what the person says: a word they have said is theirs, and is proposed thereafter; typed text is never changed.
|
||
5. What a client learns from the person's words is theirs. It **MUST** stay on their device unless they choose otherwise, and **MUST** be forgettable by them, in every language at once, with a confirmation so that no stray selection erases it. It **SHOULD** be portable between devices and clients.
|
||
6. The whole word list is chosen for one language at a time: a choice made for one language **MUST NOT** carry to another.
|
||
|
||
The reference implements this as `SuggestionScope` in `aac-core` (default `Vocabulary`), and the learned memory as `PredictionMemory` (plain data, versioned: `PredictionEngine::memory`, `restore_memory`, `forget_memory`); a conformance vector is to follow.
|
||
|
||
### §4.3 People in symbols *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
A board is used all over the world, so the people its symbols show must not default to one skin, one gender or one age. Following Unicode's emoji model (UTS #51):
|
||
|
||
1. **Skin.** A client that draws people **MUST** draw them by default in a generic, non-realistic colour — no one's skin — and **MUST** let the person choose one of the five skin tones of the emoji modifiers U+1F3FB–U+1F3FF, applied to every person in every set it can re-tone. A symbol whose skin colour cannot be changed without changing something that is not skin **MAY** be kept as drawn, and the client **SHOULD** list which.
|
||
2. **Gender.** A concept that does not name a gender **SHOULD** be drawn with a figure that reads as no particular gender, or with no figure; a gendered figure is for a gendered word (*mother*, *man*, *girl*).
|
||
3. **Age.** A concept that does not name an age **SHOULD NOT** be drawn with a child's figure: a board used by an adult shows adults.
|
||
4. The skin tone is the person's choice, kept for them rather than for a board, and changing it **MUST NOT** move or resize any cell (§3).
|
||
|
||
The reference implements skin as `aac_core::symbols::SkinTone`: the neutral is UTS #51 §2.4's own example, #FFCC22, and the five tones are OpenMoji's; hair keeps its colour whatever the tone. Its symbol build writes skin (and OpenMoji's skin shadow) as the CSS custom properties `--aac-skin` and `--aac-skin-shade` over the neutral, and lists every person symbol and its treatment in `tools/symbols/people-review.md`.
|
||
|
||
---
|
||
|
||
## §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 (§5.2).
|
||
2. **Dwell / eye-gaze** — selection by sustained gaze **MUST** use a configurable dwell time with visible progress feedback (§5.3).
|
||
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.
|
||
|
||
### §5.1 Timing belongs to the person
|
||
|
||
1. A client **MUST** let the person, or someone acting with them, set the scan rate and the dwell time directly.
|
||
2. Automatic adaptation of timing **MUST** be off unless the person opts in.
|
||
3. A client **MUST NOT** change timing silently. It **MAY** measure the person's own responses and **propose** a change, which takes effect only when they accept it — or, if they opted in, automatically under the rules of §5.2 and §5.3.
|
||
4. A proposal **MUST** be derived from this person's responses, never from a population norm alone.
|
||
|
||
### §5.2 Scan-rate floor
|
||
|
||
A scan rate that a client recommends, proposes or applies from measured responses **MUST** sit above the person's typical press, so that the highlight has not moved on when they act:
|
||
|
||
- it **MUST NOT** be derived from fewer than 10 recorded responses;
|
||
- with `M` the mean and `P95` the nearest-rank 95th percentile of the recorded response times, it **MUST** be at least `max(⌊100·M/65⌋, P95)` — the reference rule — clamped to `[300, 5000]` ms;
|
||
- a change within 10% of the current rate **SHOULD NOT** be proposed.
|
||
|
||
(Conformance C5.)
|
||
|
||
### §5.3 Dwell proposals
|
||
|
||
A dwell proposal **MAY** be shorter as well as longer — a person whose dwell is too long is slowed down as surely as one whose dwell is too short makes errors:
|
||
|
||
- it **MUST NOT** be derived from fewer than 10 selections;
|
||
- one step **longer** when more than 20% of recent selections were undone;
|
||
- one step **shorter** when fewer than 5% were undone and more than 20% of attempts were abandoned late (gaze left after at least half the dwell);
|
||
- a shorter proposal **MUST NOT** go below 300 ms; no dwell may be below 150 ms or above the configured maximum;
|
||
- an opted-in client applies at most one change per measurement window, then measures afresh.
|
||
|
||
The reference steps along the ladder `DT(X) = 300·e^(X/12) − 150` ms. (Conformance C6.)
|
||
|
||
### §5.4 Adaptation from a prior never moves a cell *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
A client **MAY** use a prior over the options on a board — a language model, or the person's own usage counts — together with the person's measured press timing. It **MAY** change only these four things:
|
||
|
||
1. the **order** in which rows, groups, blocks or cells are scanned;
|
||
2. the **emphasis** of a highlight;
|
||
3. the **dwell** each cell needs;
|
||
4. **which option a switch press selects**.
|
||
|
||
It **MUST NOT** change any cell's position or size, nor which cells a row, group or block contains (§3). The AI may rank, order, highlight or weight; the person chooses the words.
|
||
|
||
1. **Consent.** Each of these is an adaptation under §5.1. It **MUST** be off unless the person opts in. What it would change **MUST** be available to show them before they opt in and while it is on. A client **MUST NOT** apply anything other than what it shows: an adaptation shown for one board **MUST NOT** apply on another, and turning an opt-in off **MUST** discard what was applied, so that opting in again needs a fresh preview.
|
||
2. **Order.** A new order **MUST** take effect only at the start of a pass, so that a highlight never jumps mid-pass. Turning the opt-in off **MUST** restore the fixed order no later than the next pass. The reference visits units by descending prior mass and members by descending weight, with ties broken by position. This minimises the expected number of highlights before the intended one.
|
||
3. **Dwell.** A cell's weighted dwell **MUST** lie within `[max(⌈0.8·D⌉, min(D, 300)), max(min(⌊1.5·D⌋, max), D)]` ms, where `D` is the person's dwell and `max` is their ceiling; for any `D` of at least 150 ms the lower bound is at least 150 ms, and a `D` below that is never weighted below itself. A likelier cell **MUST NOT** need a longer dwell than a less likely one. A weighting **MUST NOT** change `D`, propose a change to it, or restart the §5.3 measurement window, and **MUST NOT** change the length of a dwell already in progress. Turning the opt-in off **MUST** restore `D` for every cell at once.
|
||
Because it is bounded, keyed to `D`, previewed, and undone at once, a per-cell weighting within these bounds is not a timing proposal under §5.1 item 4 or §5.3: it **MAY** be derived from a population prior such as a language model, and **MAY** be re-applied after every selection.
|
||
4. **Selection.** A press may be weighed against the person's press-offset distribution, so that a press landing just after the highlight has moved on selects what they meant. The following rules apply:
|
||
- An option **MUST** be identified by its position at its scan level, never by its rank in a pass, so that an order applied between passes cannot make one option name two cells.
|
||
- A press **MUST** be measured only from onsets that could have produced it. The reference admits an onset when the press lands between half a scan interval before it and two intervals after it.
|
||
- The distribution **MUST** be learned only from selections the person kept. The presses of every level of a selection (the row and the cell) belong to it. A selection counts as kept only after further selections have been made without it being undone — an Undo reached by scanning is itself a selection, and **MUST NOT** confirm the selection it undoes. Presses that led into a row, group or block the person then left without choosing a cell **MUST NOT** be learned, nor presses the distribution does not explain better than a spurious press. The reference learns a selection once three newer selections have been completed, so it survives two consecutive undos.
|
||
- The client **MUST NOT** act on the distribution before 10 such presses.
|
||
- The prior **MUST NOT** select on its own: the presses themselves **MUST** favour any selected option at least 4:1 over every other option, and a lone option at least 4:1 over the hypothesis that every press was spurious. The reference caps the prior's ratio between any two options at 99:4 and selects only when the leader's posterior odds over the runner-up reach 99:1; a persisted rule that would weaken the 4:1 floor is not used.
|
||
- When the evidence is short of that, the scan continues and the next press adds evidence. A level that would end after such a press — a row's single pass, or the last cycle — **SHOULD** be offered again; the reference offers at most two extra passes per visit.
|
||
- Until the person opts in and 10 presses have been kept, a press selects what was highlighted.
|
||
|
||
(Conformance C8–C11, proposed.)
|
||
|
||
### §5.5 Controls beside the board are scanned too *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
The controls a client shows beside the board that act on the message — the reference's message bar: Repeat, Delete, Clear, Speak, and ✨ (the sentence helper) when it is installed — **MUST** be reachable by switch scanning, not only where a board repeats them as cells.
|
||
|
||
1. They are scanned as one more group, the **bar**: the controls that can be pressed now (shown and enabled), in their order on screen. Selecting the bar steps into its controls one at a time, as into a row; a pass over them without a press returns to the top level, as a row's does. Timing, cycles, highlight and audio cues are the board's.
|
||
2. The person **MUST** be able to choose where the bar is scanned: **after the board** (the default), **before the board**, or **not at all**. The choice travels with their scan settings (§5) and survives a reload or restart.
|
||
3. In every scan pattern the bar is one more top-level unit: one more row in row-column scanning, one more group in group and block scanning, one more step in linear and inverse scanning. Where no board is on screen (a text mode), the bar's controls are themselves the top level.
|
||
4. Whether and where the bar is in a pass is settled when the pass begins, so the highlight never jumps mid-pass; an order from a prior (§5.4) never moves it. A bar with nothing to press is not scanned.
|
||
5. Scanning the bar **MUST NOT** move or resize any cell or control (§3): the highlight is drawn on them where they are.
|
||
6. A row the person opens from the bar (the reference's sentence helper, under the message) is scanned first while it is open: its controls one at a time, then the board as a whole. A press on the board hands scanning to the board's scan, the bar included; a choice there that changes the words, or that scan running out of passes, brings scanning back to the row. Closing the row gives scanning back to the board.
|
||
|
||
### §5.6 The way back, and help, are scanned and dwelt on too *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
A person who opens a board by switch or by gaze **MUST** be able to get back, and to ask for help, by the same means. Therefore:
|
||
|
||
1. The controls a client shows beside the board that move between boards — the reference's Back and Home — and its control that asks for help **MUST** be reachable by switch scanning as one more group, the **navigation**, as the bar is: §5.5 items 1, 3, 4 and 5 apply to it as written there for the bar. Only the controls that would do something now are in it: on the home board Back and Home are not, and help always is.
|
||
2. The person **MUST** be able to choose where the navigation is scanned — after the board, before it, or not at all — apart from where the bar is. With both on the same side of the board, the bar comes first. The choice travels with their scan settings and survives a reload or restart. For a person who used an earlier version, adding the navigation to their scan is offered, not done (§5.7 item 9).
|
||
3. Where a client selects by dwell (§5.3), the navigation's controls **MUST** be dwell targets, as the board's cells are.
|
||
4. A client **MUST NOT** give a way back to a board the person already has by moving or resizing any of its cells (§3).
|
||
5. Going to a board that is already on the way to the one on screen (as a Back cell does) **SHOULD** return to it rather than open it again on top, so that the navigation's Back never steps through boards the person has left. A cell that goes to another board and is labelled as a control (Back, Home) **MUST** show the control's word in the person's language, never a translation of the label in another sense (the body part for "back"), and its label is not vocabulary (§4.2).
|
||
6. A client **MAY** offer to go back to the home board after each word chosen on another board. It is the person's choice, not the board's: it **MUST** be off unless they choose it, and it travels with their settings, not with a board.
|
||
7. Asking for help **MUST** say its message aloud at once and show it in large print, in the person's language where its translation is trusted and in the client's own language otherwise. Where no voice speaks the person's language it **MUST** say the message in a language a voice on the device speaks (the reference: English), and say on screen that it did; where no voice can say it at all, the screen **MUST** say to show it to someone nearby. The message **MUST NOT** cover the board (the reference shows it in the message bar's place). It **MUST NOT** claim that anything was sent, nor that a translation has been reviewed by a speaker of the language when it has not.
|
||
8. A panel the client opens over the board (its settings and the like) **MUST** be operable by switch scanning and by dwell, and closable by them: its controls are scanned in their order on screen, in groups where the panel groups them, and are dwell targets; a list to choose from or a slider opens its choices (or less and more) as controls of their own. A control that would leave the client (a link to another page) is not scanned. A panel opened by someone helping **SHOULD** wait for a press of the person's switch before its scan moves, so that it never moves under their hand.
|
||
|
||
The reference scans Back, Home and Help as `ScanConfig::nav` (`BarPlacement`), names them `ScanHighlight::Nav`/`NavItem` and `ScanChoice::NavItem`, and keeps Help's messages and the navigation words with how they were read (`aac-web/src/help_messages.json`, `nav_labels.json`): each translation was read by two independent model readers, and only those both agreed on are used; a native speaker's review is still to come.
|
||
|
||
### §5.7 Switches belong to the person *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
1. A client **MUST** let the person, or someone acting with them, choose which inputs are their switches — any key, a gamepad button, a touch on the board — by pressing the switch, and **MUST** keep the choice across a reload or restart. Teaching a switch **MUST** listen only while the client shows that it is listening.
|
||
2. With two switches a client **MUST** offer step scanning: one switch moves the highlight one step, the other selects; the highlight never moves by itself, and the scan never stops under the person. With one switch it **SHOULD** offer inverse scanning: the highlight moves at the scan rate while the switch is held, and letting go selects. A client **MAY** give further switches other steps (the reference: back one step, and out of a row).
|
||
3. The hold (acceptance) and release times of §5 apply to every switch, each read on its own: a press of one switch is never taken as a second press of another.
|
||
4. A client **MUST** let the person choose the scan pattern (§5 item 1), the number of passes before a scan that moves by itself stops, and whether each pass starts at the row (group, cell) of their last choice. These change only the order in which things are visited, never a cell's position or size (§3).
|
||
5. Auditory scanning — a tone, or the name of what is highlighted, as the highlight moves — **MUST** be off unless the person chooses it. A name **MUST NOT** be said over the person's own words, nor stop them, and **MUST** be said in a voice that is not theirs; where there is no other voice, a tone is played instead. When the person asks for the whole name first, the highlight **MUST NOT** move on until it has been said, or until a time fitted to it has passed.
|
||
6. **No change locks the person out.** A change to how the person reaches the client — the access method, the switches, selection by dwell or by switch, what moves the highlight, the scan's cues (a person who scans by ear cannot scan without them), the scan rate, the dwell time, and the hold and release times — made by switch scanning or dwell **MUST** be provisional: unless it is kept, with the new way of choosing, within a stated time (the reference: 15 s), everything **MUST** go back to how it was. What it goes back to **MUST** outlive a reload: a change still waiting when the client restarts goes on waiting, or, its time up, is undone. Choosing what is already chosen is not a change. A change made by someone helping (by touch, mouse or keyboard) during the wait takes effect at once and **MUST** be kept, whatever becomes of the person's. The question **MUST NOT** cover the board (the reference asks it in the message bar's place, or at the foot of an open panel).
|
||
7. A client **MUST** refuse, and say so, a change to the switches that would leave no switch for something the access method needs (to select; in step and inverse scanning, to move the highlight). Teaching a switch an input another switch has **SHOULD** swap the two.
|
||
8. **The way out.** A person is locked out when their switch does nothing any more (it was taught away, or the access method was changed to one it has no part in). Holding down, for a set time (the reference: 8 s), a key or gamepad button that has no role in the person's current access method and is one of their switches — or, while they scan, any input — **MUST** bring switch scanning back with that input as switch 1 — kept, not replaced — keeping the person's other switches, and what moves the highlight where it still works; and **MUST** say so. For a person who looks, points or touches, an input that is not one of their switches (a hand resting on a laptop's keyboard) **MUST NOT** be counted. An input that is one of the person's working switches **MUST NOT** be counted, however long it is held (resting on a switch, or holding it in inverse scanning, is using it). Keys pressed with a modifier (⌘, Ctrl, Alt), modifiers themselves, and the keys a keyboard holds down to move or scroll are not counted, and a key **MUST** stop counting as held when a modifier comes up, or the page loses the focus or is hidden (a key-up that never comes is not a hold). It is provisional (item 6), kept only by a press of that same switch after it has come up from the hold, past the release time (a contact bouncing as it comes up keeps nothing); meanwhile the way the person chose before — looking, pointing, touching — **MUST** go on working, so that going back can be chosen with it. The timing comes back as it was before a change still waiting to be kept, or, with none, as times that lock nobody out (the reference: no scan made faster than its default, no hold time, the default release time).
|
||
9. A client **MUST NOT** change how a person who used an earlier version reaches it without asking: a person who scanned with two switches keeps what they had, and new scan steps (step scanning, the navigation) are offered once, in words. Settings a newer version adds **MUST** be kept where an older version does not overwrite them.
|
||
|
||
### §5.8 Pointing and touching *(proposed — draft for the version after 0.2.0; not part of 0.2.0 conformance)*
|
||
|
||
1. A client that selects by dwell **MUST** offer it for a pointer (a head mouse, an eye tracker that moves the pointer) as for gaze, with visible progress on the target and the person's dwell time (§5.1). It **MUST** be off for a pointer unless chosen: an ordinary mouse is the same input, and a mouse resting on a word must not say it.
|
||
2. It **MUST** offer that a target just selected is not selected again until the pointer or gaze has left it, and **SHOULD** offer that a switch selects what is pointed at.
|
||
3. For touch, a client **SHOULD** offer selection only once a touch has been held for a time the person sets, selection when the finger lifts (over whatever it is on then), ignoring touches for a time the person sets after a selection, and a first touch that says what a button is with a second that selects it. Each of these times belongs to the person (§5.1); none is applied unless they choose it. While one of them is on, the client **MUST NOT** let the page pan under the finger.
|
||
|
||
---
|
||
|
||
## §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).
|
||
6. Leaves timing to the person and keeps proposals within §5.1–§5.3.
|
||
7. States every language's core status honestly (§4.1).
|
||
8. *(Proposed, after 0.2.0.)* Adapts from a prior only by order, emphasis, bounded dwell and selection, never by moving a cell, and only with the person's opt-in (§5.4).
|
||
|
||
The [`aac-conformance`](aac-rs/crates/aac-conformance) harness checks the cascade routing table (C1), energy monotonicity (C2), the offline invariant (C3), wire round-trips (C4), the scan-rate floor against the published response-time vectors in [`conformance/v1/scan_rate.json`](conformance/v1/scan_rate.json) (C5), dwell proposals against [`conformance/v1/dwell.json`](conformance/v1/dwell.json) (C6), and language honesty (C7). It also checks the proposed adaptation from a prior against [`conformance/v1/adaptive.json`](conformance/v1/adaptive.json) (§5.4, vector version `0.3.0-draft`). These checks are labelled `[proposed]` and counted separately; an implementation of 0.2.0 is not held to them:
|
||
|
||
- that order never moves a position (C8);
|
||
- that every adaptation requires opt-in (C9);
|
||
- that weighted dwell stays within its bounds (C10);
|
||
- that selection follows the person's presses (C11).
|
||
|
||
C5, C6 and C8–C11 recompute every expected value from the raw inputs with an independent oracle before comparing the engine against it. 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. Choosing an access method, vocabulary, and communication approach is best done by the person with their team, often with a speech-language pathologist — but it is never a prerequisite: no one needs a professional's permission to start communicating with AAC. The standard provides the portable substrate; it does not replace assessment, training, or support.
|
||
|
||
---
|
||
|
||
## Proposed (draft, after 0.2.0)
|
||
|
||
- **§2 Unknown fields are kept (addition).** A reader keeps the fields of a board or cell that it does not recognize and writes them back unchanged, so a board saved by a newer client loses nothing when an older one saves it.
|
||
- **§4.2 What a suggestion may propose (new).** Suggestions (next words, sentence starts, completions) come only from the person's vocabulary and their own words, unless a language's whole word list is chosen — off by default, chosen per language, its source stated before it is chosen. A model may rank permitted words, and letter predictions may use the whole list. Nothing limits what the person says, and what is learned from them stays on their device, forgettable and portable.
|
||
- **§4.3 People in symbols (new).** People are drawn by default in no one's skin, and in any of the five Unicode skin tones the person chooses; concepts that name no gender or age are drawn with neutral, adult figures.
|
||
- **§5.4 Adaptation from a prior never moves a cell (new).** A prior may change only four things: scan order, emphasis, bounded per-cell dwell, and which option a press selects (Bayesian selection over the person's learned press timing, after Nomon). Each is opt-in, shown before it is applied, tied to the board it was shown for, and discarded on opt-out. Per-cell dwell weighting within its bounds is not a §5.1/§5.3 timing proposal. Selection learns only from kept selections — every level of them, never an abandoned row, never a selection an Undo reached by scanning undid, never a press the model does not explain — identifies options by position, and never lets the prior select. Conformance C8–C11, vector `adaptive.json` version `0.3.0-draft`.
|
||
- **§5.5 Controls beside the board are scanned too (new).** The message bar's controls are one more group of the scan — after the board by default, before it, or off, as the person chooses — in every scan pattern, without moving anything; a row opened from it is scanned first while open.
|
||
- **§5.6 The way back, and help, are scanned and dwelt on too (new).** Back, Home and Help are one more group of the scan, placed apart from the bar, and dwell targets; no way back is given to a person's own board by moving anything; going to a board already on the way returns to it; navigation cells show the control's word, never a gloss in another sense; going back to Home after each word is the person's option; help says and shows its message at once, never over the board, in the person's language where two independent readers agreed on it (in another language a voice here speaks where none speaks theirs), and claims nothing was sent nor that a speaker reviewed it; panels (their lists and sliders too) are operable and closable by switch and dwell, and wait for the person's switch before their scan moves.
|
||
- **§5.7 Switches belong to the person (new).** Any key, gamepad button or touch can be a switch, taught by pressing it while the client shows it is listening; two switches give step scanning, one can give inverse scanning; hold and release times apply to each switch on its own; pattern, passes and "start at the last choice" only reorder the visit; auditory cues are opt-in, in another voice or a tone, never over or stopping the person's words. No change locks the person out: changes made by scanning or dwell (timing included) are provisional until kept with the new way of choosing, survive a reload until kept, and never cover the board; changes leaving nothing to select with are refused; holding down a switch that does nothing for the person (never one of their working switches, nor a key that is no switch of someone who looks, points or touches) brings switch scanning back with it as switch 1, provisionally, kept by pressing it again once it has come up, while their earlier way of choosing still works. People who used an earlier version keep what they had, and are offered what is new.
|
||
- **§5.8 Pointing and touching (new).** Dwell for pointers as for gaze (off for a pointer unless chosen), with "look away before selecting again" and selection by switch; touch can select on hold, on lifting the finger, ignore repeated touches, and say a button before selecting it — all at times the person sets, with no panning under the finger.
|
||
|
||
## Changes since 0.1.0
|
||
|
||
- **§4.1 Language honesty (new).** Every language states its `CoreStatus`; an absent status reads as `GlossOnly`; glosses are never presented as a language's core vocabulary. The earlier claim that one ~400-word core covers ~80% of every language is withdrawn. Conformance C7.
|
||
- **§5.1 Timing belongs to the person (new).** Scan rate and dwell are set by the person; automatic adaptation is off unless they opt in; changes are proposed, never silent.
|
||
- **§5.2 Scan-rate floor (new).** A measured rate sits above the person's typical press (`max(⌊100·M/65⌋, P95)`, ≥ 10 responses). The previous reference rule set it to 80% of the mean press, so on average the highlight had moved on when the person pressed. Conformance C5.
|
||
- **§5.3 Dwell proposals (new).** Proposals go both ways, with floors. The previous reference could only lengthen the dwell, including by 50 ms every 30 selections regardless of how the person was doing; §5 item 2 no longer says dwell "should adapt to fatigue". Conformance C6.
|
||
- **§11** now says access and vocabulary decisions are never a prerequisite for starting.
|
||
- **Reference implementation** (not normative): the demonstrator can be mounted under a sub-path (`AAC_BASE_PATH`, `AAC_SW_URL`, `AAC_APP_TITLE`, `AAC_HIDE_ENERGY`); its Settings gain a Timing section implementing §5.1–§5.3; dwell reads a monotonic clock that works in browsers (`web-time`); 538 gloss corrections across 44 languages (`aac-core/src/gloss_audit_2026-09-28.json`).
|