cvpfus Codex commited on
Commit
5866c3e
·
1 Parent(s): 905b0bb

Document reader cursor audit evidence

Browse files

Co-authored-by: Codex <codex@openai.com>

Files changed (4) hide show
  1. FIELD_NOTES.md +6 -2
  2. README.md +5 -1
  3. app.py +12 -0
  4. scripts/verify.py +10 -2
FIELD_NOTES.md CHANGED
@@ -30,11 +30,15 @@ Runtime setup is also data-backed. `/api/runtime-setup` lists the app command, l
30
 
31
  The judge runbook lives at `/api/demo-script`. It keeps the live presentation repeatable by pairing visible actions with API checks for health, model budget, runtime setup, runtime status, image descriptions, reader narration, and speech.
32
 
33
- Accessibility evidence lives at `/api/accessibility-audit`. It records the reader-mode choices that matter most for this prototype: semantic reading order, keyboard navigation, live narration, image alt text, transcript review, user-controlled playback, and fallback resilience.
34
 
35
  ## Reader Mode Behavior
36
 
37
- The frontend creates a reading queue from semantic nodes: headings, paragraphs, quotes, figures, captions, and controls. It speaks one item at a time, keeps keyboard focus synchronized with the active node, and exposes the current narration through an `aria-live` region.
 
 
 
 
38
 
39
  Each narration is also added to a visible transcript log. This gives the demo a second accessible surface: users can review what was spoken, copy the session transcript, or clear it before exploring another part of the article.
40
 
 
30
 
31
  The judge runbook lives at `/api/demo-script`. It keeps the live presentation repeatable by pairing visible actions with API checks for health, model budget, runtime setup, runtime status, image descriptions, reader narration, and speech.
32
 
33
+ Accessibility evidence lives at `/api/accessibility-audit`. It records the reader-mode choices that matter most for this prototype: semantic reading order, keyboard navigation, reader cursor state, shortcut safety, live narration, image alt text, transcript review, user-controlled playback, and fallback resilience.
34
 
35
  ## Reader Mode Behavior
36
 
37
+ The frontend creates a reading queue from semantic nodes: headings, paragraphs, quotes, figures, captions, and controls. It speaks one item at a time, keeps keyboard focus synchronized with the active node, marks that node with `aria-current`, and exposes the current narration through an `aria-live` region.
38
+
39
+ When screen reader mode turns on, the reader cursor starts at the focused article node or the most visible article node. That makes the feature feel connected to what the user is already reading instead of always jumping back to the top of the page.
40
+
41
+ Reader shortcuts deliberately ignore form controls. A user can adjust the Kokoro voice, speed slider, and auto-advance checkbox without the page treating those keystrokes as navigation commands.
42
 
43
  Each narration is also added to a visible transcript log. This gives the demo a second accessible surface: users can review what was spoken, copy the session transcript, or clear it before exploring another part of the article.
44
 
README.md CHANGED
@@ -77,7 +77,7 @@ The verifier checks syntax, static assets, Space metadata consistency, determini
77
 
78
  `/api/demo-script` exposes a compact judge runbook with the visible actions and API checks that prove the submission claims.
79
 
80
- `/api/accessibility-audit` exposes structured evidence for semantic reading order, keyboard navigation, live narration, image alt text, transcript review, user-controlled playback, and fallback resilience.
81
 
82
  ## Screen Reader Mode
83
 
@@ -94,6 +94,10 @@ The frontend builds a reading queue from semantic article nodes. When screen-rea
94
 
95
  Each readable node is sent to the reader brain for concise narration, then Kokoro generates speech. If a model is unavailable, the app uses deterministic fallbacks so the demo remains navigable.
96
 
 
 
 
 
97
  The session panel keeps a transcript of recent narration with copy and clear controls, making the spoken path inspectable during demos and useful for the Field Notes write-up.
98
 
99
  Image descriptions are preloaded into a local cache and written into the page's real `img alt` attributes. When the planned MiniCPM-V runtime is unavailable, deterministic alt-text fallbacks keep the screen-reader path usable.
 
77
 
78
  `/api/demo-script` exposes a compact judge runbook with the visible actions and API checks that prove the submission claims.
79
 
80
+ `/api/accessibility-audit` exposes structured evidence for semantic reading order, keyboard navigation, reader cursor state, shortcut safety, live narration, image alt text, transcript review, user-controlled playback, and fallback resilience.
81
 
82
  ## Screen Reader Mode
83
 
 
94
 
95
  Each readable node is sent to the reader brain for concise narration, then Kokoro generates speech. If a model is unavailable, the app uses deterministic fallbacks so the demo remains navigable.
96
 
97
+ When screen-reader mode turns on, it selects the focused or most visible article item, assigns stable reader-node ids, and marks the active item with `aria-current`. Clicking a readable article item while the mode is on reads that item directly.
98
+
99
+ Global reader shortcuts ignore buttons, links, selects, and inputs so the voice, speed, and auto-advance controls remain usable while reader mode is active.
100
+
101
  The session panel keeps a transcript of recent narration with copy and clear controls, making the spoken path inspectable during demos and useful for the Field Notes write-up.
102
 
103
  Image descriptions are preloaded into a local cache and written into the page's real `img alt` attributes. When the planned MiniCPM-V runtime is unavailable, deterministic alt-text fallbacks keep the screen-reader path usable.
app.py CHANGED
@@ -279,6 +279,18 @@ def accessibility_audit_core() -> dict[str, Any]:
279
  "status": "pass",
280
  "evidence": "Reader controls expose Space, N, P, H, I, S, R, and Esc shortcuts through the manifest.",
281
  },
 
 
 
 
 
 
 
 
 
 
 
 
282
  {
283
  "id": "live_region",
284
  "label": "Live narration region",
 
279
  "status": "pass",
280
  "evidence": "Reader controls expose Space, N, P, H, I, S, R, and Esc shortcuts through the manifest.",
281
  },
282
+ {
283
+ "id": "reader_cursor",
284
+ "label": "Reader cursor state",
285
+ "status": "pass",
286
+ "evidence": "The active readable node receives focus, a visible outline, a stable reader id, and aria-current state.",
287
+ },
288
+ {
289
+ "id": "shortcut_safety",
290
+ "label": "Shortcut safety",
291
+ "status": "pass",
292
+ "evidence": "Global reader shortcuts ignore form controls so voice, speed, and auto-advance settings remain usable.",
293
+ },
294
  {
295
  "id": "live_region",
296
  "label": "Live narration region",
scripts/verify.py CHANGED
@@ -324,8 +324,16 @@ def verify_routes() -> None:
324
  assert_true(audit_payload["passed_checks"] == audit_payload["total_checks"], "All audit checks should pass")
325
  assert_true(
326
  {item["id"] for item in audit_payload["checks"]}
327
- >= {"semantic_queue", "keyboard_navigation", "live_region", "image_alt_text", "inspectable_transcript"},
328
- "Accessibility audit should cover reader semantics, keyboard use, live narration, alt text, and transcript",
 
 
 
 
 
 
 
 
329
  )
330
 
331
  runtime = client.get("/api/runtime-status")
 
324
  assert_true(audit_payload["passed_checks"] == audit_payload["total_checks"], "All audit checks should pass")
325
  assert_true(
326
  {item["id"] for item in audit_payload["checks"]}
327
+ >= {
328
+ "semantic_queue",
329
+ "keyboard_navigation",
330
+ "reader_cursor",
331
+ "shortcut_safety",
332
+ "live_region",
333
+ "image_alt_text",
334
+ "inspectable_transcript",
335
+ },
336
+ "Accessibility audit should cover reader semantics, keyboard use, cursor state, shortcut safety, live narration, alt text, and transcript",
337
  )
338
 
339
  runtime = client.get("/api/runtime-status")