Repository navigation
NvDA and Terminal, an Overview and constructive discussion #20934
Replies: 4 comments
|
As the person who started the recent discussion on Mastodon, I thought I should comment here. First, I have no problem with the merge being reverted. A community member proposed a fix, it was accepted, problems were found during beta testing, and the merge was reverted. This is how things should work, even if the proposed code could have been tested more in alpha. Either way, the beta test did its job, and normal procedures were followed. Leaving this patch out of 2026.3 isn't the problem. I have two main concerns. First, the way that @seanbudd wrote their comments came across, probably unintentionally, as dismissive and uninterested. Taking the conversation as a whole, it felt like Sean was saying that this freezing bug didn't exist unless someone could point to the perfect issue, and the issues others presented weren't good enough. Without the magic issue, the problem was going to be ignored. On top of this bug existing for years, this was extremely frustrating to read. As I said on Mastodon, though, my existing frustration with the situation may have colored the way I read Sean's comments. Locking discussion didn't help matters, either, as it felt like there was no interest in people actually providing the issue Sean wanted. "Provide me the exact information I want or this goes no further, but I'm not going to let you provide me with the information," is how I'd summarize the way I read things at the time. Having read this post, I can see that this interpretation was likely not accurate. The other problem I have is that of an end user who regularly uses cmd.exe at work. I do all git management, SSH commands, server admin work, and plenty more from cmd. I often issue commands that trigger the freeze. I've gotten good at piping to a file if I think the output might be too much, or quickly moving focus away from the window if I think the problem is starting. Still, I'm regularly bitten by the bug and have to restart NVDA. Doing a hard shutdown of the whole computer is rare, but it definitely happens. Anyway, my point is that I, and plenty of other users, encounter this bug all the time, and we have for years. At long last, someone took a stab at fixing it. The fix didn't work quite how it was intended to, but instead of reverting it and letting the developer fix it, the conversation was locked and the developer didn't know anything was wrong. For what a lot of us consider a critical bug, this was very disappointing. Again, pulling the feature from this version isn't the problem, it's everything around the revert that left a bad taste in my mouth. This paragraph is going to be unfair, but it's how I feel. I'm sure there is a great deal that happens behind the scenes and in discussions and issues that I don't know about. I'm sure contributors and core developers have tried to figure this out over the years. Still, from my perspective, it feels like NV Access has not bothered to fix a critical bug. When a contributor tried, they rejected the contribution with a comment that suggested the freezing bug was never brought to their attention and without letting the contributor update the code. As a long-time NVDA user, this all feels very disheartening. |
|
both the original message and the first reply are very well written. I learned a lot while closely following every word, and I was keeping an ear toward that Mastodon discussion. As something of a newbie with the idea of contributing to projects like this in general where somebody has to review and accept it or not, and also being the one trying to work out how to review it, I can see how this is actually a complex issue, and I am proud of our community for putting this much effort into working out how to make it as right as it possibly can be. I'm not sure whether it is immediately rellevent, but at a certain point @jcsteh mentioned during the Mastodon discussion that it felt like Firefox has an easier path for external contributors than NVDA currently does. If that's the case, can we consider the NVDA procedure to be convoluted enough that people are losing sight of the whole picture for knowing what they need to look for and being able to follow the steps the way maintainers want? I'm not an active NVDA contributor, most of what I do is agentic only at this point, contributing to projects that are themselves done thus. Recently I wanted to make a simple change to fix an obvious bug on another project that I had already cloned and fixed myself, and tested extensively to ensure it fixed what it fixed and didn't break anything. Luckily though, before I started making the pr, I already noticed the contribution notes, and one of those was that I would be rejected if I required AI to hold my hand. So I had to just create an issue and describe the problem instead of fixing it myself. To do that, I was asked in the template to submit code that reproduced the issue. For that, I had to produce a script to do it, and by that point I had actually done more work than the simple pr would have been. I had already proven the fix programatically, but was expected to spend more time showing how to cause it than it took to fix it, which admittedly is more a thing that happens when you're mostly agentic coding. Point being, that process felt convoluted, I had to fill out a template with the requested info, and I failed to review the whole thing first, and even when I did, I kept forgetting that I was to put the OS build or some other tidbit of info in that field on the other end of this template, not in this one I'm now in. I think of myself as reasonably intelligent, but I can only hold so much in my head at once, and the rest is noise until I come onto it again. That brings me back to what I was trying to say, if you convolute the process, you make the contributor fight themselves before they even get around to dealing with whether you will then like what they did or not, and when they have to fight themselves, they're going to miss things. The sheer amount of work required to site all those open issues, not to mention going through to see the closed issues that would have applied as well for context, it boggles the mind. It is something I'm not ready to do for free. It is also not something trivial for maintainers to make better though, I recognize that much at least. I know there are reasons and there is history present in bringing us, the NVDA project I mean, to the state that it is in terms of how contribution works and our large number of issues. In the end though, I'm just expressing my feelings and my theory without any personal experience at making a contribution successfully or otherwise to the code. I'll leave this with another note about being proud that we have progressed to the point where we are big enough to have a problem like this in the first place. |
That's true, but I said that mostly in the context of why I personally don't contribute much to NVDA these days. It takes me a great deal of time and energy to figure out which pieces of info fit where in the template, especially for the kinds of complex issues and pull requests I tend to deal with, where the template often just doesn't fit well. In contrast, Firefox doesn't generally require you to fill in templates to submit bugs or contributions. However, there are a few reasons NVDA has developed the process it has:
This is actually precisely the reason that projects have the kind of process NVDA has. You believe you tested it extensively, but my guess is that if you were heavily using AI and are not an experienced coder, you don't actually know the code well enough to be sure that it doesn't have side effects you hadn't considered. In complex code bases, changing one thing can impact another thing in weird and wonderful ways that are difficult to anticipate unless you are experienced enough to reason through those possibilities. Particularly with the rise of AI, small projects like NVDA are swamped with these kinds of contributions. It takes a lot of time to carefully review them and check for possible issues, but people primarily using AI without much knowledge of the code can just churn them out in a matter of minutes. Then they get to walk away after it's submitted and potentially accepted, leaving the core team to deal with the fallout. This is also why reverting is the right call in a situation like this terminal fix. It is better to revert to a known state with known bugs than regress users who might now depend on this working the way it did. Yes, this is a serious bug, but a fix for a serious bug does not justify introducing other serious bugs in its wake. |
It hasn't been fixed because it is very difficult to fix well. This whole situation is clear proof of that: something that was thought would fix the bug actually ended up introducing other serious bugs.
First, I agree the contributor should have been notified, and I've suggested to the core team that this needs to be part of the revert process. So if that's what you mean about not letting the contributor update it, that's fair in my opinion. That said, after a revert, the contributor is always welcome to update the code and resubmit. Keeping the change in the code base and waiting for the contributor to fix it isn't really an acceptable option because the new bug is regressing users in the meantime. |
Uh oh!
There was an error while loading. Please reload this page.
The NVDA terminal story is not one bug, and I don't think the argument is really about one revert either
A fix intended to stop NVDA from effectively losing control of the terminal was reverted because it could cause NVDA to lose terminal information.
That contradiction was what pulled me into this.
At first I thought the story was fairly simple: NVDA had a long-standing terminal freezing problem, somebody finally tackled it, a regression appeared, the fix was reverted, and contributors became understandably upset.
After going backwards through the issues, PRs, older terminal work, and the recent discussion, I don't think that version is good enough.
The problem is older than this particular fix. It is also not really one problem. There are UI Automation events, terminal buffers, diffing, LiveText, speech queuing, cancellation, Windows Terminal versus Conhost, SSH, WSL, braille, and now tools such as Claude Code and Codex that can keep a terminal changing continuously for a very long time.
Then there is a second story running alongside the technical one: what happens when an old issue is closed, the manifestation it described may have changed, but the underlying class of problem is still with us? Who carries that history forward? Is an old issue a historical record, an active work item, or somehow expected to be both?
I went into this wanting to understand who was right in the recent argument.
I came out thinking that several people were right about different parts of it, and that the more useful question is how the project can avoid having essentially the same argument again.
My conclusion up front
The high-volume terminal problem is real and old.
#20177 solved an important part of it by stopping large LiveText bursts from monopolising NVDA, but it also introduced a genuine information-loss problem by capping and superseding output.
When #20888 exposed that regression during beta, reverting the change through #20898 was a defensible release-engineering decision.
Where I think the project can improve is what happens around a revert: bringing the contributor in earlier, carrying the original problem forward into a clear successor issue, and preserving the lineage between the historical reports, attempted fix, regression, revert and next attempt.
The disagreement over whether there was “an issue” for the original problem also becomes much easier to understand once we distinguish two things:
I think both sides of the recent argument were talking past each other around that distinction.
The lineage at a glance
For anyone who wants the short map before the archaeology:
#6291 → #11002 / #15850 / #18779 → #20177 → #20216 / #20649 → #20888 → #20898 → #20902Very roughly:
That lineage is important, but I would not read it as “one identical bug remained unfixed for ten years”.
The console architecture changed. UIA changed. Windows Terminal changed. NVDA's terminal handling changed.
What persists is the failure family: terminal output can arrive in forms or volumes that cause too much work somewhere in NVDA's pipeline.
There isn't really one “terminal bug”
This was probably the first thing I had to unlearn.
When somebody says:
there are several places where the problem may actually be happening.
The terminal can generate a flood of UI Automation events.
NVDA may spend too much time receiving and processing those events.
It may retrieve a very large text range from the terminal.
LiveText may compare previous and current contents to work out what changed.
That comparison can produce a large amount of new text.
NVDA then has to report it.
The speech system has to process it.
Meanwhile, the terminal may still be producing more output.
The user may press Control to silence speech, Control+C to stop the command, or an NVDA command to inspect something else.
And Windows Terminal and the older console host do not necessarily expose text or change notifications in the same way.
Once I started thinking in those layers, some of the apparently contradictory reports made much more sense.
A change can reduce UIA flooding without fixing speech backlog.
Another can keep NVDA responsive while losing useful output.
A solution can work well in Windows Terminal and not in Conhost.
A change can improve automatic speech and still leave braille or cursor tracking with problems.
So I don't think it is very helpful to ask whether #20177 either “fixed the terminal” or “broke the terminal”.
There is a terminal pipeline, and different failures have appeared at different points in it.
The history matters, but we need to read old closed issues carefully
#6291, from 2016, describes NVDA becoming overwhelmed by large amounts of terminal text.
The details are old, so I would not use it as proof that the exact 2026 regression had simply sat untouched for a decade. But it is strong evidence that the basic user story is old: the terminal produces information faster than NVDA can comfortably deal with, and responsiveness suffers.
#11002, from 2020, is even clearer.
Its reproducer was wonderfully brutal: enable UIA for Windows Console, open Python, and print
"test"100,000 times.The report says that after several seconds, not only the console but UIA applications in general could become inaccessible until NVDA was restarted.
That tells us this was never only a question of “NVDA talks too much”. There were deeper UIA/event-processing problems involved.
Then there were architectural attempts to reduce the work rather than merely cope with it later.
#13781 is interesting here because it proposed relying more on Windows Terminal's UIA notifications and less on heavy LiveText text-change processing. The motivation included performance: the number of text-change events and the cost of handling them were already seen as major terminal bottlenecks.
That matters for 2026 because it shows that “how do we schedule all this LiveText work?” was never the only possible question.
There was already a more upstream one:
Then #15850 gives us another useful checkpoint. Its reproducers included dumping large files and generating large
git logoutput. UIA could stop responding, console output could become unavailable, and the reporter explicitly said the problem remained after earlier work intended to reduce UIA flooding.This is where I think terminology becomes important.
There is a difference between:
Those are not the same thing.
An old closed issue can be historically important without automatically being the right current engineering work item.
2025 changes the context
The issue that made me rethink the modern user story is #18779, opened in August 2025.
It describes severe Windows Terminal performance problems under high-frequency output and explicitly mentions things such as Claude Code, verbose build output and log monitoring.
The report describes long periods where NVDA stops responding properly, navigation commands fail, speech becomes unresponsive and watchdog recovery can become involved.
This predates #20177.
I think that matters.
AI coding tools did not create NVDA's terminal problems. The older issues make that impossible to argue.
But they may have changed how often blind developers run into the problem.
A terminal is no longer always:
An agentic coding session can look more like:
A workload that once looked like an extreme stress test can now resemble an ordinary working session.
That makes the old architecture newly important.
Then came #20177
In May 2026, Ethin Probst opened #20177, “LiveText: announce large bursts via a pumped generator”.
What I appreciate about the PR, reading it now, is that it did not pretend the problem was new.
It explicitly connected itself to older issues including #6291, #11002, #14189, #15786 and #15850.
Its core diagnosis was straightforward.
When LiveText detects a large amount of new output, reporting every line synchronously can keep NVDA's main thread occupied for too long. A speech call may only cost a little time, but multiply that by hundreds or thousands of lines and the screen reader starts to feel stuck.
The proposed answer was to turn the reporting into a pumped generator.
Process a bounded amount.
Yield.
Let NVDA service other work.
Continue.
That part still strikes me as conceptually sound.
But #20177 was really solving two different problems at once.
The first was scheduling:
The second was volume:
The generator addresses scheduling.
The line cap and supersession behaviour address volume by dropping output.
Those are different design decisions.
And I think the second one is where the later regression becomes much easier to understand.
Why dropping old output made sense — until it didn't
Suppose a package manager emits 5,000 lines.
Or
journalctlis streaming rapidly.Or an AI agent is rewriting status lines and printing tool output for several minutes.
By the time speech gets to line 600, it may be ridiculous to continue reading all the way through line 5,000 while the actual process has already finished.
Often the information the user really cares about is at the end:
So I understand the intuition behind preferring recent output and abandoning older queued material.
The problem is that a terminal is not only a progress display.
Sometimes every line is information.
git logis not merely progress.Compiler output may contain the one error that matters near the top.
A short command may print one useful answer and immediately return to the prompt.
So “older” is not the same thing as “obsolete”.
And this is where #20177 moved from a scheduling fix into a semantic decision about what information the user could safely lose.
That is a much harder decision for NVDA to make on the user's behalf.
There was an architectural warning almost immediately
After #20177 merged, Jamie Teh asked a question that I think should be central to the next attempt.
Why was LiveText seeing enough new text to create this kind of problem in the first place?
Historically, LiveText was often dealing with something closer to the visible screen — perhaps dozens of lines.
Bill Dengler pointed out that this assumption is no longer safe. With modern Windows Terminal and Conhost UIA, the text range can represent the whole buffer rather than only the visible portion.
That changes the scale of the problem quite a lot.
If the accessibility layer hands NVDA thousands of lines of scrollback, then an algorithm designed around screen-sized changes may suddenly be operating on a completely different kind of object.
This makes me wonder whether
_reportNewLinesis partly being asked to clean up a problem created much earlier in the pipeline.The question is not only:
It is also:
That is why I would not want the eventual replacement to be designed only around another
MAX_LINESvalue.#20216 and #20649 matter more than they first appear
One thing that gets lost if we jump directly from #20177 to the September regression is that the trade-off was already visible before September.
#20216 experimented with configurability around the pumped generator: things such as batch size, maximum lines and signalling that content had been skipped.
That version introduced hidden configuration parameters, which NV Access did not want, and it was reverted.
Later, #20649 brought back a narrower part of the idea: an audible indication when lines were skipped.
I don't think this proves that anybody should have foreseen the exact regression in #20888.
But it does show that the project had already recognised an awkward question:
To me, that is not a minor configuration question. It is part of the user contract.
And it also matters for understanding the later revert: #20177 introduced the pumped-generator and output-dropping behaviour. #20649 mainly added feedback around one consequence of that behaviour.
When #20177 was reverted, #20649 did not make much sense independently.
September: the opposite failure appears
Then Alex Hall opened #20888 against the 2026.3 beta.
Now the problem was almost the mirror image of the original one.
NVDA was not necessarily freezing.
Instead, useful terminal output could disappear from automatic speech.
A
git pullcould produce a result, but NVDA might speak only the returned prompt.A
git logcould produce many lines, but the user might hear only a small part at the end rather than the expected beginning.For a terminal user, these are both serious failures:
and:
The first sacrifices control.
The second sacrifices information.
Neither is a good endpoint.
The real design question is therefore not “was #20177 good or bad?”
It is:
Was the revert itself wrong?
My first instinct was closer to yes.
After reading the release process and the discussion more carefully, I changed my mind.
NVDA's release process is deliberately conservative once a release reaches beta. A regression introduced in the current development cycle can be reverted rather than replaced by another risky fix at the last moment, and after such a revert a replacement is very unlikely to go into the same release.
That makes sense.
The alternative would have been trying to redesign terminal output handling during beta while already knowing that one seemingly reasonable approach had produced a serious regression.
Michael Curran also said during the discussion that several people, including himself, had noticed both significant terminal slowdowns and text no longer being spoken that previously was.
So I don't think “the fix was reverted” is good evidence that NV Access handled the release irresponsibly.
If anything, reverting a risky behavioural change during beta is exactly what a cautious project should sometimes do.
This is one place where I think some of the frustration on Mastodon went too far.
But accepting that the revert was reasonable does not end the discussion.
For me, it starts the more interesting part.
The phrase “there was no open issue” did too much work
During #20898, Sean Budd said there was no open issue documenting the initial freeze.
Older reports were pointed out.
Sean's response was that they were not open, triaged issues.
There is a very important difference between these two claims:
and:
The second is a project-management statement.
The first sounds like historical erasure.
I don't think Sean meant the first.
NVDA's contribution guide now makes the workflow fairly clear: for anything other than minor bug fixes, contributors are expected to have an issue filed and triaged before substantial implementation work.
In that framework, “no open, triaged issue” is meaningful.
But from the contributor's side, look at what had already happened.
#20177 contained a problem description.
It linked the historical reports.
It gave reproduction examples.
It proposed a root cause.
It went through review.
It was merged.
So if you are the person who did that work, and then hear that there is no issue documenting the problem, I can see why it sounds as though all of that context somehow does not count.
I think Sean was talking about something quite specific: there was no current canonical issue ready for development. But I can also see why that was not how it sounded from the other side.
A little more precision would probably have prevented a lot of heat.
That says what the project actually means without making the historical reports disappear.
“This PR probably should not have been accepted in the first place”
This was one of the sharper comments in the revert discussion, and I don't think it should be polished away.
Sean's point, as I understand it, was that a problem this complex should have had a properly documented, triaged issue and more design discussion before implementation.
There is a fair lesson in that.
NVDA has been moving toward earlier discussion and architecture work for non-trivial changes precisely because late design disagreements are expensive.
But I can also see why that comment would be difficult for the contributor.
The PR had been reviewed.
It had been merged.
Follow-up work had happened.
If the project later concludes that work like this should not be accepted without an open triaged issue and earlier architecture discussion, that is a useful process correction.
But the institutional lesson belongs to the project too.
A contributor cannot retroactively make maintainers ask for a design discussion that the project did not require before merging the work.
That is one of the reasons I think the right takeaway is not “the contributor ignored process”.
It is more like:
I think the contributor should have been brought in earlier
This one seems much simpler to me than the rest.
When a recently merged community contribution is suspected of causing a regression, the original author should be tagged early.
Not because they own the bug forever.
Not because the revert should wait indefinitely for them.
Not because they get veto power over a release decision.
Simply because they know the changed code unusually well.
They may recognise the failed assumption immediately.
They may know whether a small fix is possible.
They may tell maintainers that the regression comes from a different interaction.
And there is also a human difference between:
and:
Open source projects depend on voluntary attention.
That attention is finite.
Jamie Teh raised essentially this communication point in the Mastodon discussion as well: even if the revert itself was correct, the contributor could have been brought into the loop sooner.
That criticism seems fair to me.
Then #20902 appeared
After the revert discussion, Michael Lawler opened #20902 to document the original high-output hang again in a clean, contemporary form.
The reproducer is almost comically simple:
Run that from the root of a drive, then try to stop it.
Without the pumped-generator change, NVDA can become so occupied by the stream of text that even getting Control+C through to the application becomes difficult.
This is exactly the kind of current work item maintainers were asking for.
That is good.
But it also raises a process question for me.
If reverting #20177 knowingly restores a serious failure mode, why should the existence of a successor issue depend on somebody noticing the gap after the argument has already started?
Imagine if the revert had immediately said:
Technically, almost nothing changes.
But the message becomes very different:
That is the kind of continuity I think is missing.
What I think the Mastodon discussion got right — and where I think it went too far
I wanted to check the larger claims rather than simply repeat the mood of the thread.
This is where I landed.
“The original terminal freeze was undocumented”
I don't think that is true in the broad historical sense.
There is a long history of reports involving terminal flooding, UIA stalls, diffing problems and output saturation.
But I do think the maintainers were correct in the narrower sense that there was not a clean, current, open and triaged issue representing exactly the problem the next implementation should solve after the revert.
Those are different statements.
“The revert was unreasonable”
I don't think the evidence supports that.
Once the missing-output regression appeared during beta, reverting the current-cycle change was consistent with NVDA's release policy and was probably the safer release-engineering decision.
I would not make the revert itself the centre of the criticism.
“The contributor should have been involved earlier”
I think this criticism is substantially fair.
Even if the final decision remained a revert, earlier notification would have been better technically and socially.
“NV Access does not value outside contributors”
I don't think the evidence supports that broad claim.
NV Access's own development history shows that community code makes up a substantial part of NVDA, with many community PRs and a high historical merge rate.
The project also explicitly asks community developers to help with priority work.
That does not look like an organisation trying to keep outsiders away.
“There is still a larger contributor-friction problem”
Yes, I think there is evidence for that.
And importantly, this did not begin with #20177.
The same argument was happening years ago
GitHub Discussion #15551 from 2023 is striking because it is almost the same process disagreement without the terminal controversy.
One side argued that if a user searches, finds an old issue describing the same problem, and comments there, asking them to create a brand-new issue feels wasteful. The history already exists. Making them recreate it can discourage further reporting.
The other side argued that developers should not have to read years of old comments, old architectures and changed assumptions merely to work out what is broken today. A fresh issue can be dramatically easier to understand and triage.
I can see both sides.
And I think they reveal the real design problem:
GitHub Issues are being asked to serve as both a work queue and an institutional memory.
Those are different jobs.
For a maintainer, an issue may be finished because the specific task attached to it is done.
For a user, researcher or future contributor, the issue may still be the best record of how a problem evolved.
Closing the work item can be correct while the historical thread remains highly relevant.
That is exactly what happened with the terminal history.
The old issues tell us this failure family is not new.
#20902 tells a developer what to reproduce now.
We need both.
This is where I think the larger frustration starts to look real
I don't think the right conclusion is “NV Access is hostile to contributors”.
But I also don't think merge statistics alone are enough to dismiss the frustration.
A process can be rational internally and still be exhausting from the outside.
The terminal episode contains several small frictions that accumulate.
A contributor can research old issues, build a substantial solution, go through review, get it merged, and later discover that the project still considers the underlying problem insufficiently represented because there is no current triaged issue.
A regression can be reported without immediately bringing the original contributor into the discussion.
A revert can restore the previous problem before a successor ticket exists.
A maintainer can use “no open, triaged issue” in a precise workflow sense while the contributor hears “your earlier research and implementation do not count”.
A user who searches GitHub can find a closed issue that appears to describe exactly what they are seeing and still be expected to know why they should create another one.
None of these things proves hostility.
But together they increase what I would call the transaction cost of caring.
Every time somebody has to recreate context, rediscover history, learn another process distinction or discover a decision late, the project spends a little more of that person's willingness to keep helping.
That willingness is finite.
I can also see why NV Access has become more formal
It would be unfair to discuss contributor frustration without looking at the maintainer side.
NVDA has a huge issue history.
NV Access is not a massive engineering organisation.
Every external PR creates review work, and review can be much more expensive than producing the first patch.
AI coding tools have made that asymmetry even stronger.
It is now very easy to generate a plausible-looking patch.
It is not equally easy for a maintainer to prove that the patch is architecturally sound, accessible across all the strange environments NVDA supports, compatible with old behaviour, maintainable, testable and not quietly breaking another user group.
So I understand why the project has moved toward requiring discussion before non-trivial changes, expecting a triaged issue, and using ADRs for larger architectural work.
The lesson I take from this is not “remove the process”.
It is:
The best process is one that prevents somebody from doing weeks of work before discovering the question they should have been asked on day one.
The next technical attempt probably needs backpressure, not arbitrary disappearance
One of the most interesting ideas in the Mastodon conversation came from Jamie Teh.
The rough idea, as I understood it, is to preserve a pending queue of new lines rather than simply deciding that older output can be thrown away after a hard threshold.
Speak some bounded amount.
Yield.
Schedule the next portion.
Keep NVDA responsive.
If the user cancels speech, then clear what remains pending.
That changes the semantics in an important way.
Instead of NVDA deciding:
the model becomes:
I find that much more attractive because it moves the decision to give up information closer to the user.
I don't know whether Jamie's exact sketch is the final implementation.
There are questions about speech priorities, new bursts overtaking old ones, braille, LiveText outside terminals, cancellation, and the cost of obtaining and diffing the text before any speech queue exists.
But the principle seems useful:
And maybe LiveText should not be carrying the whole burden
This is where the older architecture work matters again.
If the terminal is producing unnecessary UIA events, reduce them.
If Windows Terminal can provide meaningful UIA text notifications, use them where they are reliable instead of diffing enormous buffers.
If the API hands NVDA the whole scrollback buffer, question whether that entire range needs to participate in every change calculation.
Then, for whatever genuinely new text still reaches LiveText, use a bounded and interruptible reporting strategy.
I suspect the eventual solution will have to be layered rather than one clever constant.
Something like:
Less elegant than one magic terminal fix, perhaps.
Probably more realistic.
We also need to stop testing “the terminal” as though it were one application
This whole history makes me want a standard terminal regression matrix.
Not an enormous certification programme.
Just a small collection of repeatable stress cases that represent how blind people actually use terminals now.
At minimum I would include:
git logand pagers;dir /s-style flood;And I would test things users actually care about:
I would especially include AI-agent workloads now.
Not because NVDA should be redesigned around one fashionable class of program, but because these tools have become excellent real-world stress generators for a failure mode we have been discussing for years.
The technical problem and the governance problem strangely rhyme
This was the part I did not expect.
The terminal problem is basically a queue-management problem.
Information arrives faster than one part of the system can comfortably consume it.
If NVDA insists on processing everything synchronously, the system stops being responsive.
If it solves that by throwing information away too aggressively, the system stays responsive but the user loses something important.
The governance problem looks oddly similar.
Issues, PRs, comments, historical context and community reports arrive faster than a small maintainer team can continuously absorb them.
If every historical thread must remain the active work item forever, the project becomes impossible to manage.
If the workflow solves that by severing history too aggressively, users and contributors feel that work they already did has disappeared.
I don't think the answer in either case is:
or:
The better answer is probably backpressure, summarisation and lineage.
For terminal output, that may mean bounded queues, yielding and explicit cancellation.
For GitHub, it may mean fresh canonical issues that clearly say:
The whole history does not have to remain in the active working set.
But it should remain easy to find.
Four things I would change
1. Carry the original problem through a revert
If a substantial fix is reverted and that knowingly restores the original bug, the revert should identify the successor issue.
Reopen the old issue if it still fits.
Use an existing current issue if one exists.
Or create a clean successor.
But the chain should not end at “reverted”.
2. Bring the affected contributor in early
If a regression appears to involve a recently merged community contribution, tag the contributor when that suspicion appears, not only when the revert is ready.
This does not give them veto power.
It simply makes use of the person who knows the change best and avoids unnecessary surprise.
3. Separate current work items from historical records
A fresh issue can be the right thing for current development.
That does not mean the old history should vanish from view.
Make lineage explicit:
This would have saved me a lot of time, and I suspect it would save the next person a lot too.
4. Build the regression matrix before the next major fix
Before replacing #20177 with another substantial design, agree on the terminal workloads and behaviours the new approach has to survive.
That way the project is not discovering the product requirements only after implementation.
So what actually happened?
After all of this digging, this is the reconstruction I find most convincing.
NVDA has had a family of terminal-output performance problems for many years.
Different generations of console accessibility exposed them through different mechanisms: UIA event floods, text-range behaviour, diffing, LiveText reporting and speech workload.
Several fixes improved particular manifestations without eliminating the whole class.
Modern sustained-output tools, including AI coding agents, made the problem much easier to encounter again.
#20177 addressed one important bottleneck: large LiveText announcements monopolising NVDA's main thread.
The pumped/yielding idea was useful.
But the implementation also made a second policy decision: older pending output could be dropped or superseded.
That kept NVDA responsive in some situations while creating a new failure mode in others.
#20216 experimented with making parts of that behaviour configurable, but its hidden-configuration approach was rejected.
#20649 later added a narrower indication that lines had been skipped.
#20888 then demonstrated that useful terminal output could disappear in ordinary workflows.
During beta, NV Access chose the conservative release-engineering option and reverted #20177 and #20649 through #20898.
I think that decision was defensible.
But the revert exposed a process gap.
The original high-output responsiveness problem remained real, yet there was no clean current open/triaged issue carrying it forward.
The historical reports existed, but they were closed and belonged to older manifestations of the problem.
The distinction between “historically documented” and “currently represented by an open triaged work item” was not communicated particularly well.
The original contributor also appears not to have been brought into the regression discussion as early as would have been ideal.
That technical dispute then collided with a much older community disagreement about closed issues, duplicated reporting, historical continuity and the burden placed on contributors and users.
#20902 finally gave the restored high-output hang a current canonical place again.
So I don't see a villain here.
I see a project that made a reasonable release decision while exposing weaknesses in how technical history and contributor continuity survive that decision.
That is more interesting to me than deciding who won the argument.
Where I hope this goes
For the technical side, I hope #20902 does not turn into another discussion about finding the perfect number of lines NVDA should throw away.
I would rather start from this question:
Then build the stress matrix before merging the next fix.
For the process side, I hope the project makes the chain from problem to attempted fix to regression to revert to successor issue much more explicit.
Git is already very good at preserving code history.
I think NVDA should preserve problem history just as deliberately.
The useful lesson from this episode is not:
or:
It is that a mature project needs ways of removing something from the active queue without removing it from the shared memory.
That applies to terminal output.
And, strangely enough, it applies to GitHub too.
I would especially welcome corrections from people involved in #20177, #20888, #20898 or the related terminal work if I have misunderstood the sequence, the intended meaning of “open, triaged issue”, or the architectural constraints around LiveText, UIA notifications and terminal buffers.
If I have missed an issue or important comment, please point me to it. I would much rather improve the map than defend a neat version of the story that turns out not to be true.
All reactions