open-standards/aac/aac-rs
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science e746d7bae5 clippy 1.99: two findings the comparison missed, and one it could not have seen
The two commits before this were written against a main 903 commits older than
this one, so their comparison of clippy 1.98.0 against 1.99.1 was re-run over
every cargo root that has gained Rust code since. It found these.

Method, because the first attempt was wrong

`rustup run <toolchain> cargo clippy` does NOT select that toolchain's clippy.
`cargo` resolves the `clippy` subcommand by searching PATH for `cargo-clippy`,
and on this machine Homebrew's (1.99.1) comes first, so both toolchains reported
`clippy 0.1.99` and the comparison was of one clippy against itself. The runs
behind this commit call each toolchain's own binary by path
(`~/.rustup/toolchains/<tc>/bin/cargo-clippy`, with `RUSTC` set to match and
`RUSTUP_TOOLCHAIN` unset), which gives `clippy 0.1.98` and `clippy 0.1.99`.
Confirming the delta that way: of the 24 constants `std::f64::consts` has
carried, 1.98.0 flags 18 and 1.99.1 flags 20 — the two added are exactly
EULER_GAMMA and GOLDEN_RATIO, as the previous commit says.

What changed

- wai-quantum, engine/synth/kak.rs: `1.618_033_988_749_895` becomes
  `std::f64::consts::GOLDEN_RATIO`. This is a `clippy::approx_constant`, which
  is deny-by-default, so it is an error and not a warning. The line arrived on
  2026-10-27, two days after the comparison was made, as one of six "mixing
  weights with nothing in common" that `kak` tries in turn. The literal and the
  constant are the same f64 — both `0x3ff9e3779b97f4a8` — so no value the
  decomposition computes changes. The constant is stable well below this tree's
  1.97 MSRV (it compiles on 1.96.0). The other five weights are not flagged:
  1/sqrt(3) and Feigenbaum's delta are not constants clippy knows.
  No workflow runs clippy inside wai/wai-quantum, so this was latent in CI and
  would have met anyone who ran clippy there by hand.

- Six `assert!(x.is_empty())` the previous commit missed, five of which were
  already in the tree when it was written: aac-core (translations, prediction
  twice, symbols), access-core (scan_order) and openpay's op-connect (account).
  `clippy::assert_is_empty` is new in 1.99, is allow-by-default, and reaches
  these crates through their own `#![warn(clippy::pedantic)]`, which
  `#![deny(warnings)]` then makes an error in the two aac crates.
  Each gains a message naming the value instead of the array comparison the
  previous commit used, because none of these six is a Vec or a slice: four are
  a HashMap, a BTreeSet or `OrderDiff`, which cannot be compared to `[] as [T; 0]`
  at all, and `Vec<PredictionCandidate>` derives Debug but not PartialEq, which
  `assert_eq!` against an empty array needs. A message is what the lint asks for
  anyway — it exists so a failure prints the value rather than only "false" — and
  it is the reason the lint does not fire at the other 147 `assert!(…is_empty())`
  sites that have arrived since: with a message supplied, it stays quiet.

Not changed, with the reason

- The 1.97 MSRV. `rust-version` is the floor a consumer of these reference
  implementations must meet, not the compiler this tree builds with; raising it
  narrows who can build an open standard and buys nothing, since no code here
  needs 1.98 or 1.99. `wai-quantum-webgpu.yml` installs 1.97.0 beside 1.99.1 to
  hold that floor, and that leg is untouched.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-11-03 17:42:20 -05:00
..
crates clippy 1.99: two findings the comparison missed, and one it could not have seen 2026-11-03 17:42:20 -05:00
data fix(pagesets): the phrase sets' language note says "two independent AI models agreed" 2026-10-15 21:31:47 -04:00
third_party Merge origin/main into aac/voice-quality: bar scanning, First letters, the hotfix 2026-10-04 20:15:01 -04:00
tools Merge aac/scenes-finder into aac/ui-i18n: the way to a word on a visual scene, Label in Name, "button" in Find a word and the cell editor's "Words it says", with their English in the catalogue 2026-10-16 10:10:40 -04:00
Cargo.lock sec: close the advisory backlog across every workspace, and move the WASM sandbox off a runtime with three critical escapes 2026-10-22 09:44:59 -04:00
Cargo.toml Cargo: no minimum-supported-version floor, because the policy is latest stable 2026-11-03 17:42:20 -05:00
prerender-static.sh aac-web sw: an install waits its turn, keeps what it fetched, and downloads a file once 2026-10-18 12:14:00 -04:00
README.md aac: the reference app is the AAC Reference App, no longer "Express" 2026-10-10 22:42:12 -04:00

aac-rs — the AAC reference implementation

Rust reference for the AAC open standard. Apache-2.0.

Crate What it is
access-core The shared access kernel: access methods, switch scanning with its response calibration (SPEC §5.2), dwell with two-way proposals (§5.3), gaze estimation, voice. Four dependencies (serde, serde_json, thiserror, web-time).
aac-core The engine: boards, symbols, vocabulary, motor planning, prediction, i18n with each language's core status (§4.1), the cascade, interchange.
aac-web The AAC Reference App, the communication app of the standard (Leptos → WASM, offline-first PWA). Live at aac.transaction.science.
aac-conformance The harness: C1–C7 against the published vectors in ../conformance/v1/.

Test and conform

cargo test --workspace
cargo run -p aac-conformance --bin aac-conformance     # C1–C7; any FAIL exits non-zero
cargo run -p aac-conformance --bin gen-vectors -- ../conformance/v1   # regenerate C5/C6 vectors

Build the app as a static site

bash prerender-static.sh        # → target/site/, ready to rsync; deploy with no_cache_bust

The script builds with the wasm-bindgen CLI version the crate pins (installing a private copy if the machine's differs), prerenders the SSR shell, content-hashes pkg/, and writes a service worker that precaches the shell and every file it loads, so the installed app opens with no network.

Four optional downloads ship beside the app, each built outside git and checked against a catalogue committed here. Each is offered to the person, never fetched by itself, and runs on their device:

  • Natural voices (tools/voices/): neural text-to-speech, offered first for the person's language (in setup, and when the language changes). Of the device's own voices the best speaks (premium, enhanced, then basic), the one the person chose while the device has it, and robotic or novelty voices only when nothing else speaks the language; online voices never (access-core voice.rs, aac-web voices.rs; device-voice facts from Readium Speech, third_party/readium-speech/).
  • The sentence helper (tools/ai/): an on-device language model that turns a few chosen words into whole sentences, and suggests replies. It runs on the graphics chip only, and only in the languages it was tested in.
  • Hearing your partner (tools/asr/): on-device speech recognition that writes down what someone says to the person, for the sentence helper's replies. It listens only when asked, keeps and sends nothing, runs on the graphics chip only, and only in the languages with evidence it is accurate.
  • First letters (tools/ae/): abbreviation expansion. The person types only the first letter of each word (iwtgh), and a small on-device model offers whole sentences (I want to go home), fitting what their partner said. It runs on the listener's runtime, on the graphics chip only, never speaks by itself, and is offered only where we measured it (English).

Set AAC_VOICES=none, AAC_AI=none, AAC_ASR=none or AAC_AE=none to build without them.

Host it under your own site

The AAC Reference App reads four build-time variables (set them for both the cargo-leptos build and the prerender):

Variable Default Use
AAC_BASE_PATH "" Mount path, e.g. /app. Also set LEPTOS_SITE_PKG_DIR=app/pkg for the prerender.
AAC_SW_URL /sw.js The service worker to register (a host usually runs one for its whole site).
AAC_APP_TITLE AAC — reference app The document title.
AAC_HIDE_ENERGY unset Set to hide the energy meter.

aac.aurasense.ai builds it this way at /app (build-app.sh).

Two rules the app keeps

  • The first frame is the same on the server and in the browser. Saved state is restored only after hydration, behind a brief starting screen. Reading it earlier made a returning user's first frame differ from the prerendered page, and hydration aborted.
  • Timing belongs to the person (SPEC §5.1). Settings → Timing sets scan speed and dwell, shows proposals from the person's own responses to accept or decline, and adjusts automatically only if they turn that on.