7: What QUILL Says - transcript

Download the MP3

Jessica: The QUILL Cast, episode seven, the last of our first-steps arc. I'm Jessica, and today we tune what QUILL says, because the right amount of talking is different for every listener.

Liam: I'm Liam. Last episode Jessica walked you through control shift P, the command palette, the searchable popup that lists every command QUILL knows. The takeaway was: you never need to memorize menu paths when you can type three letters. Today we stay in that same territory, but instead of reaching commands, we shape what reaches you. Every save, every search, every "encoding changed" and "no results" is something QUILL could tell you out loud, or write on a strip, or just stay quiet about. The verbosity system is what decides.

Jessica: The honest framing: every screen reader user lives between two failure modes. Too quiet, and you miss the save that failed or the search that found nothing. Too chatty, and the tool talks over your thinking. Most software gives you a single mute button and a prayer. QUILL gives you a routing engine. The promise is simple to state: you can shape the soundscape to fit the moment, and you can change your mind at any time without losing information.

Liam: We built the system in pieces, and the layer cake is the easiest way to hold it. Layer one: channels. Every announcement QUILL can produce has a four-way choice of where it lands: speech, which goes to the screen reader and TTS; braille, which goes to a display; sound, the earcons and chimes; and visual, the status bar text. Layer two: profiles. A named bundle of channel choices plus a small amount of policy, like "sound off entirely" or "suppress routine confirmations." Layer three: modes. Quiet Mode and Meeting Mode are runtime toggles, the things you flip mid-work, and they take priority over the profile. Layer four: per-verb overrides and templates, for when you want to rewrite what QUILL actually says about a specific action. Layer five: history, the audit trail. We will walk all five in order.

Jessica: Channels first, because they are the substrate. The four are defined in quill/core/verbosity/channels.py as a flag enum. The default for a fresh install is all four on, and the code calls that the "default channel mix." A flag enum means the channels combine, so a profile can say "speech plus visual but no braille and no sound" cleanly. There is one design law that matters more than the rest, and it is in the same file: visual is the accessibility floor, and it cannot be disabled. The Prefs panel renders that checkbox as checked-but-disabled. So when you mute every other channel, the status bar still gets the text. You are choosing delivery, not choosing ignorance.


Liam: The four built-in profiles live in quill/core/verbosity/profiles.py, and they are the talkativeness ladder. Beginner gives you full context for every action, all channels, friendly chimes. Normal is informative but not chatty, and it is the default for a fresh install. Expert suppresses routine confirmations, still speaks errors, and switches sound to errors only. Quiet is the meeting-room one, speech and earcons off, braille and visual only. Notice that the ladder is not just "louder versus quieter." It is also a severity policy. Errors and warnings are designed to survive the Expert and Quiet profiles, because suppressing an error to feel less interrupted is a worse outcome than the interruption itself.

Jessica: There is also a small but important detail. There is a legacy setting called announcement_verbosity that has been in QUILL for a long time, with three values, minimal, normal, and verbose. That setting used to do almost nothing. The new verbosity system gives it a real consumer: minimal maps to Expert, normal maps to Normal, verbose maps to Beginner. So if some other tool or a tutorial says "set verbosity to minimal," you will land on a profile that actually does something. The setting finally has teeth.

Liam: A code honesty moment, because we said earlier we would do these. The user-facing order of the profile list in the pref panel is the one we just named. But in the source, profiles are defined as Beginner, Normal, Expert, Quiet in that order, and the legacy mapping I just described lives in the same file as a private constant. The screen-reader-friendly name in the UI is what you should call them; the order in the file is just an authoring choice and does not imply a hierarchy you should care about. We mention this so nobody is surprised when they open the source.

Jessica: Do this with us right now, before we go any further. Open the command palette, control shift P, and type the word verbosity. Arrow through the results. You will see "Verbosity Preferences" and "Announcement History." Take a moment to arrow through both, hear their names, then escape out. You are meeting the dialog and the panel we are about to talk about, and it is better to have touched them once before we describe them. Pause the audio, do that, then come back. We will still be here.


Liam: Welcome back. The Verbosity Preferences dialog is the place where you live for the first afternoon you decide to actually tune the system. Inside it, you pick the active profile, you see the channel checkboxes, with visual grayed out, and you can drill into per-verb settings. The dialog is built on top of the wx-free core in quill/core/verbosity, which means the same rules run in unit tests as run in the live app. There is no test-only shortcut; if the prefs panel lets you do something, the engine honors it.

Jessica: Now the runtime controls, the ones you reach mid-work. The big two are Quiet Mode and Meeting Mode, and they are the headline feature of this whole family. The bindings live in the default keymap, profile_default.json, and they are: control shift grave then Q to toggle Quiet Mode, and control shift grave then shift Q to toggle Meeting Mode. Both are chord bindings, which we will cover in episode nine, but for now, you can also reach them through the palette: type "quiet" or "meeting" and the right command comes up first. Each toggle returns a spoken transition message, "Quiet Mode on," "Quiet Mode off," "Meeting Mode on," "Meeting Mode off," which the status bar also gets.

Liam: The badge is the small detail that makes the modes feel safe. When either mode is on, the status bar shows a badge. Quiet is a Q in square brackets, Meeting is an M in square brackets, and both can show together. The status_badge method in the controller renders them in that order, so the badge you hear is the same badge you see. The reason this matters: speech is fleeting. If you forget which mode you are in, you can arrow to the status bar and find out without having to toggle anything off and back on to hear the announcement.

Jessica: The behavioral difference between the two is the part that surprises new users. Quiet Mode silences speech and earcons, and keeps braille and visual on. Meeting Mode is the presentation-safe sibling; it is stronger, it hard-mutes every earcon, and it routes speech through a reduced set. The visual floor is always there. The way to think about it: Quiet Mode is "I need to think, please stop narrating over me." Meeting Mode is "I am sharing my screen with sixty people and nothing must chirp at an awkward moment."

Liam: And every mode toggle, every profile change, every per-verb override application, gets pushed onto an undo stack. The stack is bounded, twenty entries deep, and control shift Z steps it back. That binding is registered as "Undo Verbosity Change" in the command list. The reason it is its own command and not just the regular undo is that your text undo history and your verbosity undo history are different sequences. Undoing a profile change should never also undo your last three sentences of writing. The undo stack is also one of the nicest pieces of small design in the system. Each entry records both what happened and the closure to reverse it, so stepping back through is honest. You will not undo a change only to find that the system remembers the old state but cannot get you there.

Jessica: For pulling information instead of having it pushed, the status query commands, and these are some of my favorite commands in the whole application. The first is "Where Am I." It runs, and QUILL announces your caret position, line, column, total lines. The second is "What Changed." It reads the visual line of the most recent announcement, so it is a single, decisive answer to "what just happened." The third is "Speak Status Bar." It reads whatever is currently in the status bar, on demand, even if the status bar text is not normally configured to be spoken. None of these are bound by default, which means you reach them through the palette, and that is deliberate. We will come back to why.

Liam: The interesting design move is push versus pull being first-class. Some users want every action spoken, push. Other users want a Quiet profile with the visual floor only, and they pull information by asking, "Where Am I," "What Changed," "Speak Status Bar," when they want it. Both are valid, neither is treated as a workaround. The system is not judging you for picking one or the other; it is offering the choice and getting out of the way.

Jessica: The session where I watched a power user work is when this clicked for me. They had Expert profile, sound off, visual only. They were editing a long document and they would, every few minutes, hit "What Changed" from the palette to confirm the last action. There was no narration to ignore, no chatter to step on, and the audit trail was always one keystroke away. That is a real workflow, supported, not a workaround.


Liam: Two pieces of anti-spam machinery run under the hood, and you benefit from them without ever configuring them. The first is repetition collapse. If QUILL would say the exact same thing twice in a row, within a 1.5 second window, the second one is dropped. The visual floor still updates, so the status bar is honest, but the screen reader does not get spammed. This matters most when you are holding a navigation key at a boundary, and the announcer would otherwise fire "line 47," "line 47," "line 47" three times. The code that does this lives in quill/core/verbosity/throttle.py, and the choke-point it sits at is the verbosity controller's process method. So the same rule applies whether the announcement came from the legacy announce path or from a new verb.

Jessica: The second is the announcement budget. There is an optional rate cap on how many spoken announcements can fire in a rolling 5 second window. The default is zero, which means disabled, and we strongly recommend leaving it disabled. The reason it exists at all is for the very small number of users who have a specific reason to want a hard cap, for instance, a screen reader running in a context where any speech at all is unwelcome. When the budget is exceeded, speech is dropped until the window drains, and again, the visual floor never is. A suppressed announcement does not count against the budget, because suppression happened before admission, and we did not want a Quiet Mode flood to use up your speech slots.

Liam: And the one command that always gets a reaction when I demo it: "Why did QUILL say that?" Something gets announced, you are puzzled, you run the command, and QUILL explains itself. Verb id, trigger, the active profile, the channels, the template source, what was suppressed and why, whether Quiet or Meeting Mode affected it, whether a per-verb override applied, whether the template came from a QVP pack, whether the template has validation warnings. The format is plain text, copyable, and screen-reader-friendly. The data model behind it is in quill/core/verbosity/explain.py, and the trace object is recorded on every announcement that goes through the engine. So this is not a guess; it is the actual decision tree the engine walked.

Jessica: Why this matters more than it sounds. When you are tuning verbosity, you are doing two things at once: changing behavior and building a model of what the system does. "Why did QUILL say that" closes the loop. You turn off speech for search results, you run a search, you ask why, and the trace tells you that the engine received the search.find verb, the profile was Expert, the severity was routine, and routine was suppressed. You can see your own setting working. The moment that becomes visceral is the moment you trust the system, and trust is what makes the rest of the tuning feel safe.


Liam: A word about the verb catalog, because it is the inventory the rest of the system reasons about. The 34 verbs in quill/core/verbosity/verbs.py are grouped by namespace: nav for caret movement verbs, edit for editing actions, doc for document-level events, search for find and replace, and system for errors, warnings, info, progress, and the legacy passthrough. Every verb carries a Severity, and that severity is the lever the profiles pull. Routine is the first thing to go in Expert. Warning and Error are the last things standing. Navigation and Editing are middling, and the profiles and overrides can decide whether they speak. The verb catalog is also the contract that template authors work against, and it is the data that drives the Preview command we mentioned earlier. When you preview a scenario, the engine renders each affected verb with your current profile and your current overrides, so you can hear what your changes will sound like before they happen.


Liam: For the power users, and you can file most of this for later. Per-verb overrides let you edit the template for a single verb. So if "Saved {name}" feels too terse, you can change it to "Document {name} was saved successfully," and that change applies to every save from then on. The order of spoken details, the data order, is also editable, which means you can decide whether "Line 47 of 312" or "line 47" or "of 312, line 47" is the order that reads most naturally to you. The verbs themselves are defined in quill/core/verbosity/verbs.py, and the catalog currently enumerates 34 of them, navigation, editing, document, search, system, and a legacy passthrough. The docstring honestly notes that the design prose says 44, and the code ships with 34, and the count is asserted from the catalog, not hard-coded, so the registry stays honest if the catalog grows.

Jessica: Mastery-based step-down is a more subtle feature. The MasteryTracker in quill/core/verbosity/mastery.py counts successful uses per verb, and at a configurable threshold, default 25, it offers to step that single verb down to a quieter template. The offer fires exactly once per threshold crossing; the counter resets on the offer so the same verb does not nag you on every subsequent use. And if you decline, the verb is added to a disabled set, and the offer never comes back for that verb. The point is not to teach you new shortcuts; it is to let the tool get quieter as you get stronger, on a per-verb basis. You do not have to opt into it globally, and you can disable it verb by verb.

Liam: Profile import and export is the sharing feature. A custom profile, with all its per-verb overrides and template edits, round-trips to JSON, and the file uses a QVP pack format so you can sign it, version it, and hand it to a colleague. The QVP loader in quill/core/verbosity/qvp.py is the same code that loads bundled profile packs and community-shared ones, so when you save your configuration out, you are saving it in the same shape that the ecosystem speaks. There is also a template library, with built-in scenarios you can preview before applying, and a "Preview" command that shows you what a given scenario will sound like in your current profile before you commit to the change. Tuning from evidence beats tuning from theory, and the preview is how you turn theory into evidence.

Jessica: Safe Mode, which is different from the application-wide Safe Mode, is the escape hatch. If you ever find that you have tuned verbosity into a state that does not work, and you cannot remember what you changed, VerbositySafeMode plus the reset_verb, reset_chord, and restore_builtin helpers in quill/core/verbosity/safe_mode.py let you walk any individual choice back, or restore a verb to its built-in template, without nuking the rest of your work. The undo stack we mentioned earlier, control shift Z, is the lighter version of the same idea. Both exist because the designers of this system have themselves over-tuned at midnight, and they wanted the recovery path to be obvious, not buried.


Liam: History, then, because it ties the whole layer cake together. The AnnouncementHistory class in quill/core/verbosity/history.py is a bounded ring buffer, default 100 entries, and every announcement the engine produces lands in it, with the trace attached. The visual is always recorded. The speech is recorded with the redaction flag on by default, which means token values that might contain document content are dropped; the already-user-facing rendered text is what gets stored. So the history is safe to keep on, and it is safe to share with a support contact if you are debugging. The defaults are conservative on purpose.

Jessica: The Spoken Echo, the surface you reach with alt shift E, is a related but separate piece of machinery. The Echo is the "last 20 announcements" view, a dialog that lists them newest first in a readable TextCtrl, so you can re-read them at your own pace, copy them out, or just confirm what your screen reader said three announcements ago. The Echo and the announcement history serve different purposes. The Echo is your short-term working memory, the last handful of things, skimmed. The history is the longer record, filterable by verb, profile, severity, and warnings, used when you are tuning or debugging. We mention them in the same breath because they feel like the same thing, but they are different tools. The Echo is also deliberately small. Twenty entries is enough to recover from a missed announcement, and small enough to skim in five seconds. If you find yourself wanting the longer record, the panel is the right destination, and the alt shift E shortcut is the right way to recover from a single missed moment.

Liam: One last code-verification before the homework. The status query commands, "Where Am I," "What Changed," "Speak Status Bar," are not bound by default in the standard keymap. We mentioned this earlier and we want to be honest about why. The design choice is that the most important moment to use these is when you are working in a different audio environment, and you do not want to commit muscle memory to a binding that might conflict with another application. Reaching them through the palette is two seconds of typing, and that two seconds is the right cost for a tool you only use occasionally. If you find yourself using "What Changed" ten times a day, that is the right signal to assign it a binding, and the keymap editor in episode nine is how you do that.

Jessica: The two-week starter plan we genuinely recommend, and the one we stand behind. Week one, do not touch any of it. Run the default Normal profile, learn what the announcements are, and let your ear build a model of the normal soundscape. Week two, at the end of three or four work sessions, open the Spoken Echo and notice which announcements actually annoyed you. The pattern is usually "I never want to hear X," not "I want everything quieter." So instead of switching from Normal to Quiet, turn off the one or two channels for the one or two categories that get in your way. The system is built for that kind of surgical change, and the bulk profile switch is for when you genuinely want a different mode of working, like moving from a focused writing hour to an editing-and-comparing hour. The reason the two-week timeline is the right one: tuning is a habit, not a one-time setup, and trying to optimize it on day one means you are optimizing before you have heard the defaults enough to know what you are missing. Give the system a week, then judge it.


Liam: Homework, and the homework is built around actually feeling the system. One: from the command palette, find "Toggle Quiet Mode" and run it. Notice the Q badge in the status bar. Do something that would normally produce an announcement, save, search, anything. Notice that the status bar still updates. Toggle Quiet Mode off. Notice the Q badge disappear. Two: from the palette, run "Where Am I" and "What Changed" once each, just to meet the spoken response. Three: run any announcement, save, search, whatever, then run "Announcement History" or open the Verbosity Preferences panel and find the history view, and skim the last few entries. Four: the optional stretch, run "Why did QUILL say that" on any announcement, read the trace, and notice how much of your own configuration the system is willing to show you.

Jessica: That completes our first-steps arc, the first seven of fifty-four episodes. You can install, save, navigate the window, reach any command through the palette, and now shape the soundscape. Next episode begins part two, the everyday editor, and we start with the one skill that makes everything else faster: moving through text like you own it. Movement, navigation, marks, and the difference between "I typed it" and "I got there quickly enough to keep typing."

Liam: I'm Liam.

Jessica: I'm Jessica. Say less, hear more.

Back to all episodes