Calendar: an interview nobody came to is announced to screen readers as a cancelled interview #453

Closed
opened 2026-10-01 10:46:49 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading how the calendar says an event's state in words.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at applications/agenda.py:219 (the muted= line in events_between), applications/agenda.py:95-116 (SPOKEN and its comment), applications/agenda.py:181-187 (Event.said) and templates/applications/calendar.html:42 (the sr-only span); applications/services.py and applications/ical.py have not moved.

The calendar mutes an interview when it was cancelled and when the other side did not show up, and the hidden words it reads out are keyed only on whether the event is muted. So a no-show is read as "Cancelled interview:". On screen both are only struck through, which makes the spoken prefix the one place the state is stated, and for a no-show it states the wrong outcome.

  • Where: applications/agenda.py:203 in events_between: muted=interview.outcome in {InterviewOutcome.CANCELLED, InterviewOutcome.NO_SHOW}. SPOKEN (:95-106) maps (INTERVIEW, True) to _("Cancelled interview:"), and Event.said (:165-171) looks it up by (kind, muted) alone. Drawn as an sr-only span at templates/applications/calendar.html:35. The comment above SPOKEN says ""cancelled interview" and "interview" are different facts".
  • What happens: somebody using a screen reader goes through their month. An interview recorded as They did not show up (InterviewOutcome.NO_SHOW) is read out as "Cancelled interview: Aperture Science". The rest of Postulo keeps the two apart: settle_interview writes an interview entry for a no-show and an interview cancelled entry for a cancellation (applications/services.py:505-524), and the diary file marks a no-show CONFIRMED, not CANCELLED (applications/ical.py:42-47).
  • Why it matters: the outcome is a fact about the search that a person reviews later, and a reader who cannot see the page is given a different one from the record. It also means the calendar alone treats a no-show as a cancellation.
  • Fix: carry the outcome on the event, for example a state field ("cancelled", "no_show", "done") that said reads before falling back to muted, and add a translated prefix such as _("Interview nobody came to:") for a no-show. Decide at the same time whether a no-show should be muted at all, given the diary file treats it as having happened.

Related to #274 (closed), which added the spoken state for muted events but keyed it on muted alone.

Done when

  • A test in tests/test_calendar.py settles an interview as InterviewOutcome.NO_SHOW and asserts that its Event.said is not the cancelled prefix, and that a cancelled one still is; it fails today.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading how the calendar says an event's state in words. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `applications/agenda.py:219` (the `muted=` line in `events_between`), `applications/agenda.py:95-116` (`SPOKEN` and its comment), `applications/agenda.py:181-187` (`Event.said`) and `templates/applications/calendar.html:42` (the `sr-only` span); `applications/services.py` and `applications/ical.py` have not moved. The calendar mutes an interview when it was cancelled and when the other side did not show up, and the hidden words it reads out are keyed only on whether the event is muted. So a no-show is read as "Cancelled interview:". On screen both are only struck through, which makes the spoken prefix the one place the state is stated, and for a no-show it states the wrong outcome. - **Where:** `applications/agenda.py:203` in `events_between`: `muted=interview.outcome in {InterviewOutcome.CANCELLED, InterviewOutcome.NO_SHOW}`. `SPOKEN` (`:95-106`) maps `(INTERVIEW, True)` to `_("Cancelled interview:")`, and `Event.said` (`:165-171`) looks it up by `(kind, muted)` alone. Drawn as an `sr-only` span at `templates/applications/calendar.html:35`. The comment above `SPOKEN` says "\"cancelled interview\" and \"interview\" are different facts". - **What happens:** somebody using a screen reader goes through their month. An interview recorded as *They did not show up* (`InterviewOutcome.NO_SHOW`) is read out as "Cancelled interview: Aperture Science". The rest of Postulo keeps the two apart: `settle_interview` writes an *interview* entry for a no-show and an *interview cancelled* entry for a cancellation (`applications/services.py:505-524`), and the diary file marks a no-show `CONFIRMED`, not `CANCELLED` (`applications/ical.py:42-47`). - **Why it matters:** the outcome is a fact about the search that a person reviews later, and a reader who cannot see the page is given a different one from the record. It also means the calendar alone treats a no-show as a cancellation. - **Fix:** carry the outcome on the event, for example a `state` field (`"cancelled"`, `"no_show"`, `"done"`) that `said` reads before falling back to `muted`, and add a translated prefix such as `_("Interview nobody came to:")` for a no-show. Decide at the same time whether a no-show should be muted at all, given the diary file treats it as having happened. Related to #274 (closed), which added the spoken state for muted events but keyed it on muted alone. ## Done when - A test in `tests/test_calendar.py` settles an interview as `InterviewOutcome.NO_SHOW` and asserts that its `Event.said` is not the cancelled prefix, and that a cancelled one still is; it fails today.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:46:49 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#453
No description provided.