46: GLOW for Files - transcript

Download the MP3

Liam: The QUILL Cast, episode forty-six. I'm Liam. Today GLOW leaves the editor and walks over to the file picker. Yesterday's episode looked at the document open in front of you, the buffer, the selection. Today's episode looks at the files you're about to send: Word documents, PowerPoint decks, Excel workbooks, PDFs, EPUBs, and yes, Markdown. Same engine, deeper analysis, real numbers attached.

Jessica: I'm Jessica. A quick recap of episode forty-five, since the series rule is no episode stands alone. Episode forty-five introduced GLOW, the Guided Layout and Output Workflow, an accessibility review system that turns structural problems in a document into a list of findings you can actually read. We turned on the experimental opt-in under Preferences, Experimental, and we looked at the in-editor commands: Audit Current Document, Audit Selection, Fix Current Document, Fix Selection. The fix flow opened a named preview tab, started a compare session against the original, and let you dispose of the rewrite yourself, propose then dispose, always.

Liam: A small honest correction on the recap, because we'd rather name the drift than paper over it. The earlier episode called GLOW the Guided Layout and Output Workflow, and the abbreviation certainly fits. The expansion itself is from the documentation, not from a code constant. The codebase calls the package quill-glow-core, names the seam in quill slash core slash glow dot py, and ships a function glow engine version summary that returns a string like "GLOW engine, glow, release one point three, rules two point four". The marketing layer is honest, but the code is the source of truth. When in doubt, read the code.

Jessica: Right. So today we add the file-level half of GLOW. The same engine, the same review-first contract, but applied to a structured document sitting on disk. Two new commands land under Tools, GLOW: Audit File and Fix File. The mixin that owns them is in quill slash ui slash main frame glow dot py, GlowFileMixin. That file is the handler and the dialog chooser, but it is not where the analysis lives. The analysis lives one layer down, in quill slash core slash glow dot py, behind an audit file function and a fix file function. That separation matters, because the same seam is what the future command palette, the future Quillin, or the future agent will call into. The handler is the front door. The seam is the contract.

Liam: And the front door is gated, like every experimental command in QUILL. Each handler starts with a call to ensure glow enabled, which is a small guard on the main frame that checks the experimental master switch plus the GLOW checkbox, and if either is off, it shows a message box that tells you exactly where to go in preferences and exactly which boxes to tick. If GLOW is off, the command refuses and explains. If GLOW is on, the work begins. This is the same pattern as the in-editor commands from yesterday, the same opt-in, the same discoverable refusal. Commands stay in the command palette so they can be found, but invoking them while gated tells you how to turn them on instead of silently doing nothing.


Jessica: Let's walk Audit File, because it is the calmer of the two. You invoke the command. A standard file dialog appears, titled GLOW Audit File, and the wildcard at the top lists the formats QUILL can route to the structured engine: DOCX, PPTX, XLSX, PDF, EPUB, and Markdown. The constant lives at the top of main frame glow dot py, GLOW STRUCTURED WILDCARD, and the same string is reused by the fix file picker. Pick a file, accept, and the handler does the right thing immediately: it sets the status line to "GLOW is auditing file dot docx", then it submits the work to the task manager, named glow-audit-file, with an on-success callback and an on-failure callback. Your editor stays responsive, your keystrokes keep landing where they should, the background work happens off the UI thread. Episode four's muscle memory: background work never blocks the editor. This is the same contract.

Liam: When the parse finishes, the on-success callback runs on the UI thread. It calls build file audit report, which is a small renderer in the same seam module, and then it opens the report as a named scratch tab titled "GLOW Audit, file name". The status line updates, and a screen-reader announcement says, "GLOW audit for file name, score eighty-four, grade B, twelve findings". The announce call is the line that makes the result useful by ear, because you do not have to arrow through a report to learn the verdict. The headline is spoken first, the details are in the tab. That separation is the same pattern the in-editor audit used, and it is the right pattern for a structural summary.

Jessica: The report itself, the content of that tab, has the same shape as yesterday's. Engine name on the first body line, then score, then grade, then total findings, then how many of those findings are auto-fixable. Below that, a numbered list, one finding per number, each with the severity in caps, the rule identifier, the line and column location when the engine could place it, the message in plain language, and a suggestion. The format mirrors build audit report from yesterday exactly. The only difference is the source: a buffer of text in memory for the in-editor audit, a file on disk for the structured audit. The presentation is the same. The muscle memory carries over.

Liam: The grade, the score, the letter. This is the part the previous version of this episode, the short version, called a game-changer, and we stand by that, but we want to be precise about what the numbers mean. The score comes from the shared GLOW core, from a property on the audit result the engine returns. The grade is computed by the engine, mapped to the same A through F scale most of us grew up with, and carried back as a string. The score is an integer out of one hundred, the grade is a letter. If the engine is not installed, the seam returns a fallback result with score zero, grade F, and a single finding whose rule id is GLOW-CORE-UNAVAILABLE. That is the honest degradation: no number pretending, no letter pretending, just a clear message that the engine is absent and a suggestion that the user install the optional glow extra.


Jessica: Fix File, which is the command that does the actual repair, and which is the part of GLOW I want to walk slowly because the safety property is structural, not aspirational. The handler calls ensure glow enabled, picks a file the same way Audit File does, and then computes an output path. The function glow fixed copy path takes the source and produces a sibling file with the suffix accessible inserted before the extension. So report dot docx becomes report-accessible dot docx. If that name is already taken, the function appends a numeric counter: report-accessible-2 dot docx, report-accessible-3 dot docx, and so on. The counter is the second safety property, because it means even the fixed copy will not silently overwrite an earlier fixed copy you kept around. There is no path through the function that can produce a name collision. The original file name is the prefix, the source directory is the directory, and the engine is responsible only for writing to the path the function produced.

Liam: Then the handler shows a confirmation dialog. The message is, verbatim, "GLOW will write a repaired copy of file name to full output path. The original file is never modified. Continue." Two buttons, Yes and No, defaulting through the dialog style. If the user picks No, the handler sets the status line to "GLOW fix cancelled" and returns. The work is gated on a second human confirmation, after the first one of selecting a file. That is two confirmations before any disk write happens, and the first confirmation named the destination. The user knows where the file will land before they say go. That is the contract: name the destination, confirm the destination, then act on it.

Jessica: When the work runs, it follows the same background pattern as the audit. The handler submits a task named glow-fix-file, the engine fixes the file on the task manager's thread, and the UI thread stays free. When the engine returns, the on-success callback builds a report that includes the fixed-copy path, the number of applied fixes, any warnings the engine produced, and a post-fix audit. The post-fix audit is the verification step: the same engine that audited the original audits the repaired copy, and you see the new score and the new grade side by side with the old. The repaired copy is opened in a named scratch tab, the notification system logs a structured entry, and the screen-reader announcement says, "GLOW applied N fixes. The repaired copy is file name." A status line update closes the loop. Original untouched, fixed copy on disk, report in a tab, three results to verify.

Liam: The verification step is the part that turns this from a one-shot tool into a workflow. The post-fix audit tells you the deterministic fixes GLOW could do on its own. The remaining findings are the judgment calls. A link labeled "click here" can be auto-detected, but a useful replacement is a writer's choice. An image with no alt text gets flagged, and the engine can attach an empty alt attribute for decorative images, but the meaningful alt text for an informative image is a writer's job. GLOW handles what is mechanical. The author handles what is human. The post-fix audit makes the boundary explicit, by name and by number, in the report tab.


Jessica: A do-this-now beat, before we get into the engine underneath, because the workflow is easier to internalize than the architecture. Pause the audio. Open QUILL. Find a real DOCX file on your machine, a report, a handout, anything. Open the Tools menu, then GLOW, then Audit File. Wait for the report tab to open. Read the first line, the engine name, the score, the grade. Don't fix anything yet. Notice how the score and grade change how you read the rest of the report. Resume the audio when you have a number in your head.


Liam: Welcome back. Now, the engine underneath, because the trust needs specifics. The structured file analysis does not live in QUILL itself. QUILL ships a seam. The shared GLOW engine is an optional Python package, quill-glow-core, that QUILL imports if it is present. The seam is in quill slash core slash glow dot py, and the import lives in a function called load glow core. That function tries to import quill-glow-core. If the import succeeds, the seam has a real engine. If the import fails, the seam has a fallback. There is no third state. The function glow backend available returns True when the engine is present and False when it is not, and the audit and fix functions check that flag at the top. When the engine is absent, the audit returns a no-score result with the GLOW-CORE-UNAVAILABLE finding, and the fix returns a no-op result with a warning that says the engine is not installed and no changes were made. The user always gets a report. The user never gets a crash.

Jessica: The other half of the seam is the engine version. There is a function glow engine version summary that returns a one-line human-readable string. When the engine is installed, the line says "GLOW engine, backend name, release version, rules version". When it is not, the line says "GLOW engine, not installed". No hand-waving, no "best effort", just an honest read of the environment. This is the same honesty discipline as the rest of QUILL: the system reports its own state clearly, even when its own state is that the optional piece is missing. The About dialog uses this function, the diagnostics use it, the engine update flow uses it. One source of truth, one line, one meaning.

Liam: The trust model for the engine itself, which is the part that earns its place in the production-and-trust arc. The update path lives in quill slash core slash glow updates dot py, and it is built to mirror the trust model of the main QUILL updater. Every URL is HTTPS, every host is allow-listed by the same validation the main updater uses, the update manifest is HMAC-signed and verified before any download starts, and every wheel in the manifest is SHA-256 verified after the download completes. The signing key is read from an environment variable, falling back to a built-in salt when the variable is not set. The verification is constant-time. A failed checksum removes the partial file. A failed install rolls back to the vendored wheels, the offline floor that ships with QUILL itself, so the runtime is never left in a half-updated state.

Jessica: The update flow is a manifest of wheels. Each wheel has a filename, an HTTPS URL, and a SHA-256. The signed manifest says which wheels make up the new engine, and the runner downloads them, verifies each one, and installs them with pip in offline mode. The pip install uses no-index and find-links, which means pip is forbidden from reaching the public index. Only the verified, already-downloaded wheels are eligible to install. The new engine loads only after a restart, and the user is told that explicitly. The "download, verify, install, restart" sequence is the same trust ladder the main QUILL updater climbs, and the rollback directory is the safety net under every rung. If a step fails, the previous version is reinstated and the user gets a result object that says so.

Liam: A note on size, because the brief asked for honesty. The contract wheel, quill-glow-core, is lightweight. The companion backend, acb-large-print, is heavy. It depends on pandas, onnxruntime, pymupdf, and a few other large packages, and the manifest carries the size on the wire so the UI can show the real number before the user consents. The default consent for an update is "no", the same as the default consent for an audit, and the consent is asked at every step. You can check for an update without downloading, and you can download without installing. Three gates, three yeses from the user, and a free rollback at every gate. The pattern is the same one the main updater uses for QUILL itself, and it is the right pattern for any code that mutates the runtime.


Jessica: Privacy posture, stated plainly, because this audience has earned the right to be told up front. The default GLOW workflow, both episodes' worth, runs entirely on your machine. The structured audit and the structured fix call into the local engine, the local engine reads the file from disk, and the result comes back. No network call. No upload. The optional networked features, the ones in the constant GLOW NETWORK FEATURES, are three: AI alt-text generation, PII redaction, and WCAG language processing. Each is off by default. Each lives behind a GlowNetworkConsent dataclass whose every field is False unless the caller constructs the consent object with the matching flag set to True after obtaining explicit, per-action user consent. The default audit call forwards no consent, which means it forwards no feature-enabling option, which means the engine runs its on-device deterministic rules only. The confidential report stays on the box.

Liam: The structural guarantee is in the seam, not in the policy. The audit function accepts a keyword argument called consent. When consent is None, the function passes an empty kwargs mapping to the engine, and the engine sees nothing that would activate a network feature. When consent is a GlowNetworkConsent with a feature set to True, the function forwards only the enabled feature ids to the engine, and the engine decides what to do with each one. There is no global "GLOW may use the network" switch. There is no "GLOW may use AI for everything" toggle. There is a per-feature, per-call consent, and the consent is constructed by the caller, which in this codebase is the UI layer, which in this codebase only constructs it after a human has agreed. Trust through structure, not through promises.

Jessica: And the engine's own defaults mirror the same discipline. The AI alt-text feature generates image alt text with a cloud model. It does not run unless the user opts in for the call. The PII redaction feature uses Presidio, an open-source recognizer, to find and redact personal data. It does not run unless the user opts in. The WCAG language processing feature analyzes readability and language through a networked service. It does not run unless the user opts in. The audit and fix of a confidential report is the floor, and the floor is local. The networked features are the ceiling, and the ceiling is per-action consensual. A blind professional auditing a confidential HR document gets the audit they asked for, the report they asked for, and no other calls home.


Liam: The workflow this unlocks for organizations, which deserves naming. A single person with QUILL can be the accessibility gate for a whole team's outbound documents. Files go in, graded and repaired copies come out, and the findings list becomes teaching material for the authors. What used to require enterprise remediation software is now Tools, GLOW, Audit File, Fix File, in two commands, on a keyboard, by ear. The post-fix audit turns every fix into a before-and-after comparison the team can read in a meeting, and the grade turns the work into a number that moves over time. The structure is the same as the rest of the production arc: deterministic fixes for the mechanical work, judgment calls surfaced for the human work, and a record of both that the team can keep.

Jessica: A small honest correction up front, because the previous version of this episode named a narrower list. We said, in passing, that the four formats are Word, PowerPoint, Excel, PDF, and EPUB, and the audit works on those. The wildcard in the picker is wider: it adds Markdown, so MD files on disk can also be audited and fixed through the same commands. The shared GLOW engine, when installed, understands any structured document format the engine itself supports, and the picker opens the door to every format in the wildcard. The narrower list was a teaching convenience, not a cap. If your team uses OpenDocument or RTF, the picker will only route Markdown, DOCX, PPTX, XLSX, PDF, and EPUB into the seam. Anything outside the wildcard needs the in-editor audit on a buffer, the path from yesterday. The contract is honest, and the contract's edges are visible.

Liam: And one more correction, because honest correction is the house style. The previous version said the output filename is "report dash accessible dot docx", with a hyphen. The code in glow fixed copy path is "report-accessible dot docx", also with a hyphen. The function inserts the literal string "accessible" after the stem and before the suffix. The story was right, the rendering had a tiny typo. Spelling it correctly matters because the counter suffix is also a hyphen, "report-accessible-2 dot docx", and a reader who is listening for the separator will hear it. The story is the same. The words are sharper now.


Jessica: A second do-this-now beat, the one that turns the engine-understanding into muscle memory. Pause the audio. Open QUILL. Pick a DOCX or EPUB file you have audited before. Run Tools, GLOW, Fix File. When the confirmation dialog appears, read the destination path out loud, character by character, until you can hear the suffix. Say yes. Wait for the report tab. Notice the new score, the new grade, the warnings list. Notice the path of the repaired copy in the report. Open the source folder in your file manager. Confirm with your ears and your eyes that the original file is unchanged and the accessible copy sits next to it. Resume the audio when you have confirmed the original is untouched.


Liam: Welcome back. One more thing about the engine update, because the trust model only matters if it is reachable. The UI surface for it lives, like every other command, behind a menu path. The exact label is something we want to verify against the live menu before you go hunting for it. Episode two covered the download trust model in general, and the GLOW update flow reuses that trust model wholesale: same HTTPS, same allow-list, same signed manifest, same SHA-256 verification, same rollback. The GLOW-specific additions are the HMAC signature on the manifest itself, the wheel-level checksums, and the offline pip install with no-index. If you want to read the full sequence, the file is quill slash core slash glow updates dot py, and the functions are check for glow update, download glow wheels, install glow wheels, and apply glow update, in that order. The apply function is the orchestrator. Each piece is independently testable, and the tests use a fake command runner so the install step never shells out to pip in CI.

Jessica: The version-to-version comparison is the part that closes the loop. The function check for glow update fetches the manifest, reads the installed engine version through glow engine versions, and returns a GlowUpdateCheck with three things: the installed version, the available version, and a boolean saying whether the available version is newer. The version comparison itself, is newer version, is the same helper the main QUILL updater uses, so the semantics are consistent across both updaters. A new manifest version with a higher semver than the installed one is an update. The same version is not. A lower version is not. A missing installed version, when the engine is not yet installed, is treated as an available update, so the user can install the engine for the first time through the same flow. One path, two cases, no special-casing in the UI.


Liam: Homework, four steps, all doable in a sitting. One: run Tools, GLOW, Audit File on any Word document on your disk. Receive your first grade. Receive it with humility, we all start humbled. The score is a number, the grade is a letter, and the findings list is the menu of what to work on. Two: run Tools, GLOW, Fix File on the same document. Verify, in your file manager and by file size and by modification time, that the original is untouched and the accessible copy sits beside it. Compare the before and after scores. Three: open Preferences, Experimental, confirm both checkboxes are on, and run Tools, GLOW, Audit File again to see the same command from a different angle. Four: open the Tools menu and look for a Help submenu item that names the GLOW update flow, and read its label out loud. Even if you do not run it, knowing it is there is half the trust.

Jessica: One thing we want to name for the next-episode setup. Tomorrow, episode forty-seven, is the Author Tools Mega, three destinations in one sitting. The Audio Studio, the one we met in episode thirty-three, with its batch speech and chapter workbench and podcast feeds. The DAISY talking book export, the wx-free module in quill slash io slash daisy dot py that turns your editor buffer into a folder any DAISY reader can open. And the braille production surface, the submenu under Tools and its repair mixin, the part that turns QUILL into a braille-aware author tool before any embosser sees paper. Same posture as today: no silent overwrites, no reads from stale files, format-specific dialogue. We are seven episodes from the end of the arc, with the trust, community, and finale to come.

Liam: The series is fifty-four episodes in total. Forty-six down, eight to go. The arc so far has covered the editor, the command palette, the document workflow, the file menu, the AI side, the accessible vault, the story studio, and the GLOW review family. The post-production era is here. Tomorrow we ship the deliverables, and after that, the trust and community arc, and the finale. We are past the middle, in the home stretch.

Jessica: I'm Jessica.

Liam: I'm Liam. Grade it before they read it.

Back to all episodes