The remote-control grab-image command saves a relative path inside the test artifact folder, and its reply names where the file really is (ANTS-5132)
Links and highlights stay correct on busy output when trigger rules are set (ANTS-5078)
With a trigger rule that colours or links matching text, a burst of
output could leave clickable links and highlight colours on the wrong
place on lines printed later in the same burst. Those lines are now
rechecked when the screen is next drawn.
Exporting from the terminal's right-click menu tells you when it fails (ANTS-5078)
Export Scrollback as Text or HTML and Share Block could leave a
half-written file on a full disk and say nothing. They now write to a
temporary file that replaces the old one only when everything was
written, and show a message in the status bar when an export fails.
Right-click command actions always act on the command you clicked (ANTS-5078)
With shell integration, right-clicking a command offers Copy, Re-run,
Fold and Share. If new output arrived while that menu or the Share
dialog was open, the action could land on the neighbouring command, so
Re-run could type a different one. Each action now remembers which
command you clicked, and does nothing if that command is gone.
The verify-config trust prompt lists every gate and can remember a repo for good (ANTS-5082)
When Claude asks to run a repo's own verify commands, the prompt now
lists how many gates would run and their names, and "Trust this repo"
has a checkbox (on by default) to ask again if the file changes. The
trust file keeps the date each entry was first trusted instead of
resetting it on every save, and Ants warns when that file can be read
by other users.
Claude can no longer freeze the window by asking for a terminal's whole history (ANTS-5219)
Claude's scrollback tool took any line count and read all of it on the
window's thread. It now returns at most 10,000 lines, trims to the same
size limit as reading a tab's text, and marks a reply that was cut so
Claude knows it did not get everything.
The review dialogs no longer build every lane's brief at once (ANTS-5082)
Starting a review built the full brief for every lane up front and held
them all in memory while only a couple ran at a time. Each brief is now
built when its lane actually starts, which keeps memory inside the review
budget.
A background audit started by Claude no longer leaves its thread behind (ANTS-5080)
An audit Claude starts in the background is run on its own thread. That
thread was cleaned up only through the object that tracks such audits, so
if that object went away mid-audit the thread was never freed. The thread
now cleans itself up when the audit finishes.
Pasting a large screenshot no longer freezes the window while it saves (ANTS-5077)
Pasting an image saved it as a PNG on the window's own thread, so a large
screenshot froze every tab until the file was written. The image is now
saved in the background, and its path is pasted once the file exists.
Long unbroken lines no longer leave tens of megabytes cached per tab (ANTS-5077)
The drawing cache kept a fixed number of text runs, however long each run
was. A line with no spaces is one run as wide as the row, so a few tabs of
such output could hold tens of megabytes after it stopped. The cache now has
a budget for the amount of text it keeps, and very long runs are drawn
without being cached.
Closing a tab whose shell is stuck no longer risks freezing the whole window (ANTS-5077)
When a tab's background reader was still busy two seconds after the tab
closed, it was forcibly killed, which can freeze the window if it held a
lock at that moment. It is now left to finish on its own and clean itself
up.
A clickable link that wraps off the bottom row stays clickable on both lines (ANTS-5076)
A link printed near the end of the last row wraps and scrolls the screen.
Its recorded start row did not move with the scroll, so the link was
dropped from both lines. It now keeps a span on each.
A large paste now reaches the shell whole, closing marker included (ANTS-5075)
A paste bigger than the terminal's write queue used to lose its tail, and
could lose the bracketed-paste end marker, leaving the shell stuck in paste
mode. The paste is now fed to the shell in slices as it reads, and keys
typed during a long paste arrive after it.
The audit drift checks no longer freeze the window, and audit_run keeps them under its time limit (ANTS-5067)
The Audit dialog runs its spec, contract-doc and changelog drift checks on
a background thread, so terminals keep updating and Cancel works while a
check runs. A result that arrives after Cancel or a new Run is discarded.
audit_run now counts these checks in its aggregate time cap; one still
running at the deadline is reported timed_out and marks the run partial.
CI's Release job finishes again, and fails red instead of silently cancelling when it runs long. (ANTS-5188)
cppcheck now runs in its own CI job, multi-threaded with a cache of its
analysis. The Release job's build and test steps each have a time guard,
its compile cache is saved even when a run stops early, and its tests run
two at a time.
doc_citations no longer checks a bare line number against a file named in an earlier paragraph. (ANTS-4923)
A line reference like :120 on its own now borrows a file only from a
citation in the same paragraph. After a blank line or a heading it is
reported as unresolved, instead of a confident result about whatever
file the previous section happened to mention.
doc_citations no longer reports citations inside a review loop-log row as stale. (ANTS-4918)
A citation on a Cold-eyes loop-log table row is still listed, marked
loop_log_row:true and counted, but only:"stale" leaves it out, since a
landed loop-log row is never edited. A line reference that follows a
quoted path from another project is now foreign_path too, instead of a
missing_file warning that could never be cleared.
Re-importing a roadmap no longer rewrites the wording of each item's plain-English summary (ANTS-4955)
Summaries are now stored without their closing full stop and written
back with one, whichever route saved them. Each roadmap file gains
the stop on summaries that lacked it at its next render: a one-time
diff.
A line such as ```json inside an open code block no longer ends the block, so the headings and text after it stay treated as code by the outline, spec log, feedback and changelog tools (ANTS-4987)
Matches the CommonMark rule that a closing fence carries nothing after
its backticks. Files with Windows line endings still close their blocks,
and the code-block mask now shares the same rule as the other readers.
The MCP socket answers a malformed request line with a JSON-RPC parse error instead of closing silently after five seconds (ANTS-5089)
A remote-control client that stops reading a large reply is disconnected after 30 seconds instead of holding the socket open (ANTS-5093)
The Test Audit dialog drops a collected report when its chunk now covers different test files, so stale findings are not filed (ANTS-5102)
The status bar and tab dot follow a Claude session that was started before its first message, instead of showing it as idle for the whole session (ANTS-5156)
The per-tab tracker now keeps looking for the session's transcript
until Claude Code creates it, and no longer borrows another project's
transcript in the meantime.
indie_review_partition says why it ignored a .indie-review/partition.json (map_rejected with a reason, such as a missing "version": 1) and no longer reports that file as the source it used. (ANTS-4846)
New tab shells no longer inherit a dead Claude Code session's identity variables, which switched transcript saving off in a claude started there; other CLAUDE_CODE_ settings still pass through. (ANTS-4541)
The per-tab thinking-level chip reads the last prompt a person typed instead of stopping at a tool reply, so it no longer shows Unknown on almost every live tab. (ANTS-1892)
invariant_check's scope note now says on every reply that specs are matched by path, so a spec citing the module only by symbol is known to be missing even when another spec matched. (ANTS-4972)
apply_edits flags a batch that applied some edits and skipped others with partial:true (would_be_partial:true on a dry run), instead of a bare ok:true. (ANTS-4856)
roadmap_log op:"set_body" accepts a replacement body up to 65536 characters, so long bodies can be written back whole; amend_body keeps its 4096-character fragment cap. (ANTS-4841)
co_change_family, docs_index, feedback_query and session_orient now declare the compact argument they already honoured, so a caller can pass compact:false to them. (ANTS-4657)
roadmap_query's tool detail now says when parseable_bullets and its warning appear, and that a store-served read never carries them, so their absence can be read correctly on either backend. (ANTS-4964)
roadmap_query answers a migrated project whose store holds no items from the store, with zero items, instead of falling back to the file and telling the caller to Read it. (ANTS-4861)
roadmap_query names the kind or source filter when it empties a result, instead of blaming the ID filter and calling the roadmap malformed. (ANTS-4971)
Roadmap writes leave a roadmap file untouched when its content has not changed, and list it under files_unchanged rather than files_written. (ANTS-5016)
workspace_search no longer warns about short terms when the whole regex is one word-bounded group, such as \b(TODO|FIXME|TBD|XXX)\b. (ANTS-5139)
file_outline lists gtest TEST, TEST_F and TEST_P blocks as Suite.Case, and no longer reports locals declared inside a test body as functions. (ANTS-5019)
mutation_probe refuses a baseline that collected no tests (pytest exit 4 or 5) as baseline_did_not_run, naming the test command, instead of reporting the suite as red. (ANTS-4852)
file_outline lists out-of-line C++ constructors and destructors, so read_region can fetch them by name, including a bare ~ClassName. (ANTS-5021)
mutation_probe, verify_changes and the test-results cache read ctest's all-passing summary ("100% tests passed out of N"), so a green run counts as green and require_green_baseline can pass. (ANTS-4996)
feedback_query flags a shipped id with no recorded ship date as possibly_stale_binary, marked stale_check:"no_shipped_date", instead of leaving the check silent. (ANTS-4843)
roadmap_query says when it applied a different body cap than the max_body_bytes asked for, with body_cap_clamped and the effective value, on an id or ids fetch. (ANTS-4981)
ants-terminal --remote waits for a slow first byte of the reply, up to its overall deadline, instead of printing "no response" while the server is still answering. (ANTS-5138)
workspace_search resolves a glob or exclude_glob containing / against lane when one is set, instead of returning no matches. (ANTS-5117)
A refused MCP call narrowed with fields no longer lists every requested field as unmatched, so the refusal's own code is the only cause shown. (ANTS-4979)
find_definition finds C functions whose return type, name and parameter list sit on separate lines, the style common in older C code such as DOOM. (ANTS-4828)
find_definition no longer lists a wrapped ternary arm (: sym(a);) or a stream insertion (out << sym(i);) as a declaration of the symbol. (ANTS-4924)
An offloaded reply's per-row preview now samples each object row's own JSON, so every head shows what its row is instead of the same {"v": prefix. (ANTS-5153)
tools/perf-report.sh -R <regex> --save-baseline now keeps every other benchmark's saved numbers instead of replacing the whole baseline. (ANTS-5137)
The git diff reader ends a file's hunks at a merge-conflict section instead of assigning its lines to the file before it. (ANTS-5111)
The debug log now rotates when it passes its size limit during a session, instead of growing until Ants restarts (ANTS-5110)
read_log refuses a path that is not a regular file, so a named pipe can no longer freeze it (ANTS-5110)
Review Changes no longer lists a repository's whole history on every refresh when it has no remote, and a crashed git command no longer refreshes the window twice (ANTS-5109)
A line break in a changelog entry's summary, id or dated headline stays on that line and can no longer create a fake heading (ANTS-5108)
project_query no longer refuses every query for the rest of the session after 64 slow queries (ANTS-5107)
A query worker that was left running past its deadline and later
finishes now frees its slot.
project.read refuses anything that is not a regular file, so a named pipe can no longer hang a query (ANTS-5107)
Two open Ants windows no longer corrupt each other's saved tabs (ANTS-5106)
Each process now writes its own temporary file before replacing a saved
session or the tab order.
A failed tab-order save (for example on a full disk) keeps the previous tab order instead of replacing it with a cut-off file (ANTS-5106)
read_region clips an oversized first line to its byte limit instead of returning a huge single-line file whole (ANTS-5103)
An automatically sized results page always includes at least one row, so following next_offset can no longer loop forever (ANTS-5103)
codebase_index reports a failed cache write instead of ignoring it (ANTS-5103)
The AI client reports an error for a successful reply it cannot read, instead of an empty answer that looks like success (ANTS-5105)
A proxy login page or any other body that is neither a stream nor a chat
completion used to show nothing in the AI chat and read as a clean
review lane.
Build-error fix hints recognise GCC's curly quotes, so they work with this machine's compiler output (ANTS-5102)
verify_changes no longer loses ctest's failed-test list when one large chunk of output arrives at once (ANTS-5102)
An Independent Review lane now stops at its time limit even when the AI endpoint keeps trickling data, and a reply over 10 MiB is cut off (ANTS-5101)
The debt sweep's automatic fix no longer corrupts bytes that are not valid UTF-8 elsewhere in the file (ANTS-5101)
spec_conformance refuses a pattern that does not compile instead of passing every no-match row against it (ANTS-5100)
doc_lint's table-of-contents fix recognises code blocks the same way the check that reports the gap does (ANTS-5099)
It used its own simpler rule, which could insert a contents row in the
wrong place.
docs_index reports a failed cache write instead of ignoring it (ANTS-5099)
indie_review_fold_in's narrative mode honours dry_run and no longer writes ROADMAP.md on a preview (ANTS-5097)
verify_changes no longer serves a cached pass when git status fails or times out (ANTS-5097)
A failed status used to hash as a clean tree; that snapshot is now
marked uncacheable.
session_message returns at most 200 messages per inbox call and refuses a message_id that is not a positive whole number (ANTS-5098)
A limit of 0 or less used to return the whole mailbox.
changelog_log add_batch accepts at most 200 entries per call (ANTS-5098)
A roadmap flip_batch or annotate_batch where no item resolves in the roadmap database now reports failure under its own name instead of success (ANTS-5095)
The review-kind warning on append_batch also names the ids the batch
assigned rather than the headlines.
mutation_probe writes the mutated file and the restored original atomically, so a full disk or crash cannot leave a source file cut short (ANTS-5096)
build_target_for validates its cmake_path argument, and file_outline accepts at most 100 paths per call (ANTS-5096)
Editing a roadmap item's plain-language summary, source or evidence through roadmap_log can no longer break a line in ROADMAP.md or split an evidence path (ANTS-5094)
The single-field edit now cleans values the way adding an item does.
roadmap_query's report mode refuses a since or until date it cannot read instead of quietly reporting a different period (ANTS-5094)
The Claude permissions window says when its settings file cannot be read, and the transcript window no longer shows an empty User line for each tool result (ANTS-5092)
The Background Tasks window reads each task's output from the exact path it checked, and reads a finished task's output only once (ANTS-5092)
The roadmap window's kind filter covers every roadmap kind, and a roadmap file over 8 MiB is no longer cut off (ANTS-5088)
Perf, security, feature and six other kinds can now be filtered, and a
kind filter no longer hides them. The live roadmap is read up to 64 MiB.
Publishing the roadmap refuses a path that leaves the project before creating any folder, and never writes through a symlink that points outside it (ANTS-5087)
A dry run no longer creates folders either.
On a pass-headings roadmap, a hand-added pass block is protected from being deleted by the next roadmap write (ANTS-5087)
The write now refuses and names the block, as it already did for
ordinary bullets the database has never imported.
Roadmap migration and export rebuild match item ids with non-ASCII letters the same way the roadmap database does (ANTS-5087)
The database folds only A-Z when comparing ids, while the migration and
the rebuild also lowercased letters such as Ä, so those ids could link to
the wrong item or none.
An older Ants build meeting a roadmap database from a newer build now refuses at once instead of waiting for the write lock (ANTS-5086)
The new roadmap database file is also created owner-only before any
roadmap data is written into it.
Since-last-run audits no longer re-count header findings as new or grow the recorded finding list every run (ANTS-5085)
A finding a tool reports in an unchanged file that the previous run
also had is carried forward once, not added again.
Suppressing an audit finding no longer rewrites the whole rule-quality history file (ANTS-5085)
The history is saved at the end of a run and when the audit window
closes, and only when something was recorded.
Audit context filters skip very large referenced files, and the review false-positive ledger cache is thread-safe (ANTS-5085)
Audit auto-fix repairs files with Windows line endings, and the audit cache folder is always created private (ANTS-5085)
Auto-fix used to treat every planned repair in a CRLF file as out of
date; it now applies them and keeps each line's ending. The SARIF and
HTML exports and the gitleaks config writer create the .audit_cache
folder owner-only from the start.
Audit window: the Since baseline filter and changed-lines scope no longer hide every finding, and batch AI triage is throttled (ANTS-5084)
A run with Since baseline on keeps the changed-line data that filter
needs. When git cannot say what changed (a short history, a timeout, a
failure), the status line says so and the changed-lines filter is
skipped instead of hiding everything; a repository with fewer commits
than the window counts every line as changed. Batch AI triage sends two
batches at a time through one shared network client, refreshes the list once at the
end, and stops reading a reply past 10 MiB.
Audit window: project detection no longer walks build trees, and exports, labels and the changed-files filter are correct (ANTS-5084)
Opening the audit window lists only the top few folder levels when
detecting Docker and Terraform files. The signal banner shows one percent
sign. A finding containing an HTML comment opener can no longer blank the
HTML report. A
tool that failed to start is labelled a tool issue, not a timeout. A
failed export says so. A changed oo.cpp no longer matches src/foo.cpp.
Audit auto-fix skips findings suppressed after the run, and the contract-drift lanes keep every finding (ANTS-5083)
Auto-fix now checks suppressions when it runs, skips findings with no
line before reading any file, and does not read very large files. The
per-check findings cap no longer applies to lanes that are uncapped on
purpose.
A suppression that could not be saved no longer hides the finding, and a new audit run re-reads source lines (ANTS-5083)
The audit dialog now checks the suppression file write before hiding
the finding and says so when the save fails. Each run clears the cached
source lines, so an edited file is shown as it is now.
The themed stylesheet header comment now matches the rules it builds (ANTS-5082)
A mistyped colour in a custom theme now uses the default colour instead of turning black, and an oversized theme file is skipped (ANTS-5082)
The About dialog no longer describes a GPU renderer the terminal no longer has (ANTS-5082)
Clicking Re-review while a review is still running no longer wipes that round's failures, so a failed lane can't be mistaken for a clean one (ANTS-5082)
A full disk can no longer replace the verify trust list with a cut-off file, and a damaged trust file is kept aside instead of being overwritten (ANTS-5082)
A global hotkey that the desktop refuses to register now shows the 'Global hotkey unavailable' message instead of failing silently (ANTS-5081)
The global hotkey now works on desktops that start their shortcut service on demand (ANTS-5081)
A tab's tooltip keeps naming the tool Claude is using instead of being reset to a generic state on every redraw (ANTS-5081)
The Public/Private repository badge recovers when the gh tool is missing or stops responding, instead of never updating again (ANTS-5080)
Restoring the window position through KWin no longer leaks a helper process or leaves the loaded script behind when a step cannot start (ANTS-5081)
The Review Changes button no longer shows the previous tab's git state after a quick tab switch, and a stuck git check can no longer freeze it for the session (ANTS-5080)
Start-up cleanup of old MCP sockets now removes only real sockets owned by you (ANTS-5080)
Exporting scrollback now tells you when the file could not be written, instead of reporting success (ANTS-5079)
Moving or centring the window through KWin no longer leaves a stray process and temp file behind when the helper cannot start (ANTS-5079)
Connecting to an SSH host no longer risks a crash if the new tab closes straight away (ANTS-5079)
Copying a very large selection with formatting no longer builds hundreds of megabytes of styled text (ANTS-5078)
Formatted copy now groups characters that share a style, and above a
size limit copies plain text only.
Claude running in a split pane now lights its tab's status dot, and closing a pane or a split tab releases what it was tracking (ANTS-5079)
Split panes were never registered with the Claude and background-task
trackers, and closing one left its shell listed in them.
A search pattern that can match an empty spot no longer hides the real matches later on the same line (ANTS-5078)
Jumping to a search match or a bookmark now moves the scroll bar too (ANTS-5078)
Right-clicking with a very large selection no longer pauses while the whole selection is copied just to measure it (ANTS-5078)
A terminal recording no longer garbles a character whose bytes arrived in two pieces (ANTS-5078)
A background image keeps its shape instead of being stretched to fit the window (ANTS-5077)
A command's duration never shows as negative when the system clock steps backwards (ANTS-5077)
Drawing the terminal no longer builds a highlight cache entry for every line when no highlight rules are set (ANTS-5077)
In broadcast mode, Ctrl key combinations and accepted suggestions now reach every pane (ANTS-5077)
Ctrl+C, Ctrl+arrows and accepting an autocomplete suggestion went only
to the focused pane, and did not clear a highlighted selection.
A pasted screenshot's path works at the prompt even when the paste folder has spaces, and the saved file is private to you (ANTS-5077)
The saved screenshot's path is now quoted like a copied image file's,
the file is readable only by you, and nothing is announced when saving
fails.
A tab whose shell failed to start no longer behaves as if a shell were running (ANTS-5077)
Turning on the underline debug log no longer slows output, and the log stops growing past a fixed size (ANTS-5076)
Resizing the window no longer glues together words that were split across two lines (ANTS-5076)
When a line wrapped exactly at a space, resizing dropped that space and
the words on either side ran together.
Clickable links disappear when the text under them is cleared or overwritten (ANTS-5076)
A link stayed clickable over blank space after the screen or line was
cleared, and redrawing the same link over and over kept piling up
copies of it.
Sixel images decode faster, so a crafted image can no longer stall the window as long (ANTS-5076)
Each pixel was set through a slow general-purpose call; the decoder now
writes pixels directly and skips drawing past the image edge.
A garbled terminal control code no longer spills its leftover characters onto the screen (ANTS-5075)
When a program sent a control code with a stray byte in it, the terminal
gave up on the code and printed the rest of it as text. It now discards
the whole code, the way other terminals do.
Clearing the screen now always clears a text selection, even when the clear arrives in two pieces (ANTS-5075)
The terminal looked for the clear-screen code inside each chunk of output
it read, so a code split across two chunks was missed and the old
selection stayed highlighted.
A shell opened on a desktop session with a very large environment now receives every variable, including the one Claude Code uses to find the terminal (ANTS-5075)
The terminal copied its environment into a fixed-size list and stopped
when the list filled, so the variables added last were lost. The list
is now sized to fit.
Opening a long Claude transcript no longer freezes the window while the whole file is decoded (ANTS-5089)
The transcript viewer shows only the last 2000 entries, but it decoded
every entry in the file first, on the window's own thread. It now decodes
just the entries it shows and only counts the rest.
Claude's status shows up for a Claude session started from a subfolder or subshell (ANTS-5089)
Ants found the Claude session's transcript by looking at the shell's
current folder. If Claude was started after changing folders in a
subshell, that folder belonged to a different project, so no transcript
was found and the status stayed blank. Ants now looks at the folder
Claude itself is running in first.
Reading terminal text over remote control no longer copies the part it throws away (ANTS-5093)
When a get-text reply was over its size limit, Ants copied the whole
dropped part just to count its lines. It now counts them from what it
already holds.
Tabs without Claude running no longer make Ants read every process's details every two seconds (ANTS-5089)
To spot Claude Code in a tab, Ants checks the shell's child processes
every two seconds, and when none was Claude it also read the details of
every process on the system. That full scan now runs once every five
checks for a tab with no Claude running, and on every check while one is.
The Claude transcript viewer and session summaries no longer drop messages longer than 64 KiB (ANTS-5089)
Ants read Claude Code's transcript one record at a time but stopped at
64 KiB, so a long tool result or a pasted file was split into pieces that
could not be read and was silently left out. Records up to 16 MiB are now
read whole, and a larger one is skipped cleanly instead of in fragments.
Saving a large answer with many rows to disk no longer slows down sharply as the row count grows (ANTS-5104)
When a big MCP answer is saved aside, Ants builds a short per-row preview
that has to fit a size budget. It rechecked the size by rebuilding the
whole preview after every row, so the cost grew with the square of the row
count. It now keeps a running total and builds each row once, with the
same preview as before.
Ants no longer rewrites Claude Code's settings.json on every launch, and no longer replaces a hooks value it cannot read (ANTS-5104)
When the Ants session hook is already in place, starting Ants now leaves
~/.claude/settings.json untouched instead of rewriting it. A "hooks" value
that is not an object, or a "SessionStart" value that is not a list, is
now refused with a warning instead of being silently replaced.
Calls to tool names that do not exist no longer grow the token usage counter, and each MCP call does less bookkeeping (ANTS-5104)
Every made-up tool name used to add its own permanent entry to the
per-session token counter. They now share one "(unknown tool)" entry,
still counted as failures. The tokens-saved chip also reads its total
directly instead of rebuilding and sorting the full report on every call.
The tokens-saved chip shows 1M instead of 1000K for counts just under a million (ANTS-5104)
A count that rounds up to the next unit (999,950 and above) now moves to
that unit, so it reads 1M rather than 1000K, and the same for M to B.
Reading a large saved MCP answer page by page no longer garbles characters at page edges (ANTS-5104)
read_spill could end a page in the middle of a multi-byte character,
which showed as a replacement character and threw the page length off.
Pages now end on a whole character, and each page reads only its own
part of the saved file instead of the whole file.
Suspending the computer or changing its clock no longer lets two audits run on one project (ANTS-5090)
The short read cache, the "already running" guard for audit_run and
indie_review_dispatch, and the async audit job list now measure elapsed
time on a monotonic clock. A clock step backward could keep a cached read
fresh, and a suspend could free a guard slot while its sweep was still
running.
A "too busy, retry shortly" answer is no longer remembered and repeated for a cached MCP verb (ANTS-5090)
When the dispatch queue was full, the refusal for a cached read verb
was stored in the short-lived read cache, so the next call got the
same refusal after the queue had drained. The refusal is no longer
cached.
Large answers from background MCP verbs no longer stall the Ants window while they are prepared (ANTS-5072)
The reply transforms (etag, field projection, compaction, hints,
offload and the data wrap) now run on the dispatch worker for verbs that
already run there. The window thread keeps only the cache insert, the
usage record and the socket write. Measured before the change: a 4 MiB
reply cost about 92-95 ms on the window thread.
changelog_query finds an id cited only in a dated topic's headline or prose (ANTS-5145)
A dated topic heading written by changelog_log op:add_subsection is now
an entry of its own: its text is the headline and its body the prose
under it, so an id lookup reports an id cited there instead of calling it
missing.
Remote-control and MCP tab tools act on the window you last used, not on a hidden first window (ANTS-5121)
Delivered by the shared listener (ANTS-5144): each request goes to the
most recently active visible window, whose tools act on that window.
Closing a New Window window no longer cuts MCP, Claude hooks and remote control off for every other window (ANTS-5144)
Each window used to take the three socket paths from the window before
it, and closing it removed the socket files. Now one listener per path
serves the whole process: requests go to the most recently active
visible window, and a hook event goes to the window whose tabs track
its session. A second Ants process no longer takes the remote-control
socket from the first.
The sanitizer build builds again (ANTS-5143)
The perf benchmarks are no longer built when ANTS_SANITIZERS is on, so a
full build-asan build and its test suite complete, and the pre-push
hook's ASan leg runs again.
changelog_query returns every entry for an id lookup (ANTS-5147)
An id or ids lookup now ignores offset and limit, as its
design and roadmap_query do, so offset:10 no longer returns an empty
page for an id that is present.
A malformed extended-colour code no longer sets text attributes (ANTS-5136)
An SGR 38, 48 or 58 introducer whose selector is neither 2 nor 5 now
abandons the rest of the sequence. Before, ESC[38;1m applied bold
and ESC[48;3m italic.
changelog_query refuses an id or ids of the wrong JSON type (ANTS-5146)
A number, boolean or object passed as id or ids now refuses
bad_args instead of returning the whole changelog.
changelog_log add_subsection refuses a date it cannot parse (ANTS-5148)
A date that is not a valid yyyy-MM-dd date now refuses bad_args,
so every dated heading it writes is one changelog_query can read.
changelog_query reads entries under dated topic headings (ANTS-5071)
A ### <date> <Category> — <headline> heading, the form
changelog_log op:add_subsection writes, now sets the category named
after a valid date. Its bullets are returned, found by id lookups and
counted in version_index. ANTS-3533 § 3 and INV-10 were amended first.
plan_template's includes_tests:false now drops each task's test file line and test-first steps (ANTS-5068)
The option was documented and parsed but never read, so false returned
the same skeleton. The remaining steps are numbered from 1; the default
output is unchanged.
The window no longer freezes while a --remote search, tree walk or git command runs, and the roadmap store is no longer used from two threads at once (ANTS-5073)
Remote-control socket routes whose MCP twin already runs off the GUI
thread now run on the same MCP dispatch worker, with the reply written
later. ANTS-5051 closes with it. indie_review_dispatch still freezes
the window for a review.
A synchronous audit_run no longer freezes the window for the whole sweep (ANTS-5035)
It replies from a completion slot instead of joining its worker on the
GUI thread. A second synchronous call for the same project while a
sweep runs is now refused with already_running.
Closing a second Ants window no longer makes Claude commands in the remaining window refuse (ANTS-5142)
The window no longer stalls while Claude writes to its transcript. (ANTS-5050)
The task and background-task trackers now read only the newly
appended part of the conversation log instead of re-reading up to
16 MiB of it every time Claude writes. Measured on a 65 MiB
transcript, one update went from 258 ms of frozen window to 0.09 ms.
Whenever the log cannot be resumed safely — truncated, replaced or
rewritten — the full read still happens, so nothing is missed.
Leftover text styling is cleared when a foreground program exits. (ANTS-5135)
A program interrupted while printing dimmed text used to leave the dim
attribute set, and on distributions whose shell prompt carries no colour
reset of its own — openSUSE's default among them — every later prompt and
everything typed stayed dim. Ants now clears the character attributes when
a program hands the foreground back to the shell. Shell builtins keep their
styling, since they never leave the shell's own process group.
A malformed colour escape no longer leaves the text after it dim (ANTS-5130)
An extended-colour sequence too short to carry its colour had its own
selector run as an attribute code, switching dim on for every cell that
followed until the next reset. Such a sequence is now abandoned whole.
Closing Review Changes now cancels its background git probes before they are torn down (ANTS-5128)
Closing the window while a probe was still running destroyed it mid-flight,
which ran the probe's completion handler against the half-closed window.
The probes are now stopped first, on every way the window can close —
the Close button, the parent window, and quitting the app.
The Review Changes window no longer freezes on a huge diff: it shows the first 1 MiB with a note, skips redrawing when nothing changed, and ignores an older refresh that finishes after a newer one (ANTS-5059)
The roadmap window reads its "last touched" dates in the background and can no longer put a date on the wrong card when the roadmap changes mid-read (ANTS-5047)
The audit window's Debt Sweep tab scans in the background, so the window stays usable while it runs and after every fix or allow click (ANTS-5057)
The audit window no longer freezes after a run while it looks up who last changed each flagged line; it asks git once per file in the background and fills the names in when they arrive (ANTS-5040)
Saving roadmap changes no longer re-adds up the whole change history for every row it writes, and a history size that cannot be measured now refuses the write instead of switching the size limit off (ANTS-5046)
A push interrupted during its Qt 6.2 compile check now stops that check's container, and the next check does not trust the half-built tree (ANTS-5124)
The "Close tab?" question box now matches the Ants theme, can be resized and remembers its size (ANTS-5123)
The build no longer prints its GCC warnings, and the tests they pointed at still check what they read (ANTS-5114)
project_query refuses a file too large for its memory limit before reading it, and its Lua callbacks no longer leak memory when a query runs out of room (ANTS-5070)
Code searches stop reading ripgrep's output past a size limit and say the answer is partial, instead of holding all of it in memory (ANTS-5052)
The Claude status tick stops reading saved conversations once none of the rest can be the live one (ANTS-5048)
project_query stops building a result as soon as it is over its size limit, so a small Lua snippet can no longer exhaust memory (ANTS-5069)
Independent Review and Cold-eyes never walk into build and dependency folders (ANTS-5058)
The test-audit partition never walks into build folders, walks the project once for all patterns, and keeps a project that sits inside a folder named build (ANTS-5062)
doc_citations reads each quoted document once per call, inside its read budget and size limit (ANTS-5054)
The subsystem lane cache is locked, so the window and the MCP worker can read it at the same time safely (ANTS-5074)
The Compiler Warnings audit check can finish, and no longer leaves a build folder behind in /tmp (ANTS-5039)
A verify_changes gate that times out stops everything it started, with SIGTERM first so a build can stop cleanly (ANTS-5063)
A timed-out or cancelled audit check, and an audit_run tool past its time cap, stop every process the tool started (ANTS-5038)
The review engines share one locked file cache with a size limit, so the window and the MCP worker no longer write one cache at once (ANTS-5056)
recent_errors finds every missing-include hint in one project scan instead of one scan per symbol (ANTS-5053)
recent_errors reads a line the terminal wrapped as one line, so an error wider than the pane is reported whole (ANTS-5061)
co_change_family clips a long match in one pass, so a very long line no longer stalls it (ANTS-5066)
Closing a tab while its Background Tasks window is open no longer risks a crash; the window closes with the tab. (ANTS-5049)
The test-result tools now name the tests that failed, not just how many failed. (ANTS-5064)
The link checker no longer reports false broken links in a document too large for it to read; it skips that document instead of reading part of it. (ANTS-5055)
The test-audit summary returns one page of reports when no page size is given, instead of all of them. (ANTS-5065)
An audit of recent changes checks the whole project when git fails, instead of reporting a clean result. (ANTS-5043)
This covers a repository with no branch called main, a mistyped tag,
and a git call that times out.
Dialogs remember their size when you close them with the close button or Esc. (ANTS-5037)
Filtering or sorting audit results no longer lowers how serious findings look. (ANTS-5041)
A line that two tools both flag is now ranked higher, as intended.
Scrolling back through a command's output stays smooth even when that output is huge. (ANTS-5027)
The command name pinned at the top while you scroll is now built from
only as much text as fits, instead of rereading the whole output on
every redraw.
Closing a window now asks first when a program such as an editor is still running in any of its tabs, as closing one tab does. (ANTS-5120)
The question offers the same "don't ask again" choice as the tab one,
and turning it off applies to both.
A program that floods the terminal with output no longer holds up Ctrl+C and other keys, and a finished shell is reported once. (ANTS-5026)
Ants stops reading as soon as it falls behind and resumes when it
catches up, instead of queueing output without limit.
Terminal output can raise at most ten desktop notifications a minute per tab. (ANTS-5033)
A program or file that prints notification codes in a loop no longer
starts a notification process for each one.
Closing one of several windows closes its tabs and ends their programs, including the original window, which used to keep them running out of sight. (ANTS-5118)
The last window still keeps its tabs for the next start. The tabs
close a moment after their window, so a logout that closes every
window still saves them all.
A second window (File → New Window) opens with one fresh tab instead of reopening every saved tab, and a restart brings back the tabs of every open window. (ANTS-5032)
Saved tabs are restored once per run, into the first window. Each
window now saves the whole run's tab list rather than only its own,
so the last window to save no longer drops the others' tabs.
Changing View -> Opacity updates terminals that are already open (ANTS-5034)
audit_run reports a tool that ran out of time as timed out, not crashed, and ignores its half-finished output (ANTS-5044)
A saved tab that cannot be restored keeps its session file, restores all or nothing, and very large scroll histories save only what can be restored (ANTS-5031)
Re-running a command reads the right line after the scroll history has filled up (ANTS-5029)
Opening a link from the suspicious-link warning is safe while output keeps streaming (ANTS-5028)
Dialogs keep remembering their size after a second window closes (ANTS-5036)
Audit runs and project queries no longer leak memory, and the everyday checks now catch new leaks (ANTS-3847)
Each audit tool's process kept itself alive and was never freed, and
a refused project.read or project.list skipped its cleanup. Both are
fixed. The sanitized test runs before a push, in tools/ci-parity.sh
and on CI now check for leaks, so a new one fails the run instead of
going unnoticed.
Closing Ants while a Claude tool call waits on the window no longer hangs (ANTS-5113)
At shutdown, a tool call already waiting for the window thread used
to wait forever while the window waited for it. Shutdown now releases
that call without running it, so Ants exits.
The verify.json trust prompt opens on the main thread (ANTS-5025)
verify_changes runs off the GUI thread, so the "Trust
.ants/verify.json?" prompt used to be built and run on a background
thread, which Qt does not allow. It now always opens on the main
thread. If Ants is shutting down, no prompt is shown and the
untrusted commands are not run.
indie_review_dispatch replies instead of hanging Ants (ANTS-5024)
The verb's worker now receives the project root the provider has
already resolved on the GUI thread. It used to resolve the root
itself, which asked the GUI thread for every tab's cwd while the GUI
thread was waiting for that worker, so every call froze Ants for good.
Ants's own git checks can no longer make your git commit fail with "index.lock: File exists" (ANTS-4999)
Every read-only git check Ants runs now skips git's optional index
lock. That covers the Review button's two-second check, the git MCP
verbs, audit scoping and the Claude git-context hook. A hook that is
already installed picks this up when reinstalled from Settings.
The AI review job pool reports a finished round exactly once, even when a job completes the moment it starts (ANTS-5000)
Before, each nested step announced the same round again. Only test
code reached this path; live AI requests always finish later.
Four end-to-end checks now fail when the typed command never runs (ANTS-5013)
The ANSI colour, CJK, scrollback and resize cases looked for text the
typed command already contained, so the terminal's echo satisfied them.
Each now looks for text only running the command can produce.
AI answers from a provider that ignores streaming now appear, and a server's own error message now reaches you (ANTS-5007)
LlmClient keeps the raw reply until an SSE line proves it is a stream,
then reads a plain JSON answer or error body whatever the HTTP status.
Reaching the AI answer size cap now ends the download (ANTS-5008)
The request is aborted at LlmClient::kMaxBytes and reported as a
truncated answer, even while the server holds the connection open.
Closing an AI-backed window mid-request no longer crashes the app (ANTS-5002)
An AI client destroyed with a request in flight now shuts down
quietly. The audit dialog's AI triage could reach this when closed
mid-answer.
Long AI answers that arrive all at once are delivered whole (ANTS-5015)
An answer longer than one parsing pass, sent in a single burst by a
fast or local AI server, used to come back cut short with no warning.
Review dialogs report a failed AI request as a failure, not a clean review (ANTS-5003)
A lane whose request failed now shows the error in its tab and is
named in the status line, and it is left out of the results. Test
audit's resume now retries such a chunk instead of treating it as
reviewed.
The review dialogs' Dispatch button is disabled while a round runs (ANTS-5004)
A second click mid-round used to wipe the collected reports and pay
for every lane again.
Dispatching a review with no lanes says so instead of reporting a finished review (ANTS-5006)
The sanitizer CI job's test step has room to finish again (ANTS-5011)
Passing runs were finishing within a minute of the 16-minute limit,
and three were cut off at it. The limit is now 22 minutes, re-measured
from recent runs, and the job's overall cap rises to match.
The end-to-end test cases wait for the screen instead of sleeping a fixed second (ANTS-5012)
A slow instance, such as the sanitizer build in CI, no longer fails
them. Each case now polls for its expected text for up to about 15
seconds.
The blocked-roadmap-write message now describes the rule the code actually enforces (ANTS-4749)
A roadmap write blocked for a missing plain-language summary told you
the summary had to be the first line of your note. It never did — the
key may lead any line of the note. Following the old wording cost
nothing; reading it as exhaustive led you to conclude a fix would not
work when it would.