Repository navigation
aterm v0.104.0
aterm v0.104.0
2026-10-15 · 313 changes since v0.103.0
Features
- devtools: read the Developer Tools switch, prune stale copies, and hand the owner the pane
- doctor: a
devtools:row says when macOS checks each new program aterm starts, and the fix
Fixes
- aterm-agent: a Claude home with no projects/ holds no transcript, and no restart resumes a conversation without one
- aterm-agent: a harness restart's relaunch that ended at once is stopped then and reads as agent-down
- aterm-gui: the relaunch limit is said only for an exit it kept from coming back
- aterm-agent: a signalled agent that has exited is gone, reaped or not
- aterm-agent: a relaunch reads as ended only once its line's command was seen to run
- aterm-agent: a relaunch stopped as never picked up whose agent came up after all is reopened and carried on
- an upgrade stopped after its exit is asked about by its own row alone, and no-resume is said as what happened
- aterm-agent: wait_exit reads a Linux zombie as exited
- the turn end's task read is the agent's own Claude records
- aterm-phase: a footed Dialog two columns in under the inline
─rule is read whole - aterm-phase: a key-hint footer Ink wrapped over several rows is read as one
- aterm-gui: an input method's commit holding a control character is a paste
- aterm-objc: ClassPtr::from_ptr is unsafe, so safe code holds only real classes
- aterm-gui: an input method's commit of one control key stays a typed key
- aterm-cli: signals wake the session loop through a self-pipe; the session ends with its shell
- aterm-net: idle unauthenticated sockets no longer lock token holders out of the network drive
- aterm-net: rule 2 never cuts a lighter address's handshake for a heavier address's newcomer
- aterm-net: the listener's slots and the watchdog's claim get a ty model, Tier-0 and Tier-1
- aterm-gui: a Containment tab's OSC 52 reaches no clipboard
- aterm-gui: a Kitty t=t file is unlinked in the directory that was judged
- aterm-sandbox: Containment's resource limits bind; Safety's are said to be soft
- aterm-gui: a Containment tab gets no Kitty file medium and no desktop notification
- aterm-gui: a refused smart-title answer is an error naming its status, and a refused warm-up fails
- aterm-gui: a loopback-classified smart-title endpoint is dialed at loopback, never at what its name resolves to
- aterm-gui: a provider's error message is checked whole, before the excerpt's cut
- aterm-update-core: a roster key the schema does not declare is refused, not dropped
- aterm-winsign: the signer is the chain's leaf, which signtool prints last, not its root
- aterm-observe: a row the scan budget could not read is undecided, so
gonewaits instead of latching - aterm-net: the serve slot's handle is a tenure, not a lock guard
- aterm-alloc: SmallVec's by-value iterator is opaque, so safe code cannot forge or rewind it
- aterm-alloc: ArrayVec::retain keeps the undecided elements when its predicate panics
- aterm-alloc: a panicking element destructor no longer leaks every element after it
- aterm-alloc: retain's rejected-element destructor panic is held to std
- aterm-once-cell: unsync get_or_try_init refuses a reentrant init, as upstream does
- aterm-gpu: impl_pod_zeroable! proves its field list exact with an exhaustive pattern
- aterm-gui: one-component names are judged raw, so "link/" never reaches through a symlink
- aterm-dirfd: the docs say Arg carries paths and the one-name rule is the caller's
- aterm-render: text-keyed memos hash under a per-process secret
- aterm-effects: the done-mark index hashes under a per-process secret
- aterm-gui: a draft journal is named by a keyed MAC of its URI, not a public hash (hashclock-2)
- aterm-gui: a clean legacy journal never hides a keyed draft, and no open sets one aside silently (hashclock-2 review)
- aterm-verify: a checker's --version is bounded by a hang detector, as aterm-spec's is
- aterm-grid: a scroll after a rows-only grow appends at the ring's logical end
- aterm-core: the resize fuzzers check that a bottom line feed scrolls every row
- aterm-grid: pin the top-anchored region's scroll after a rows-only grow of a wrapped ring
- aterm-ctl: a peer's mail body is shown on a terminal, not obeyed
- aterm-control: the control path's JSON escapes what a terminal acts on
- aterm-ctl: a server's status lines and refusals are shown on a terminal
- aterm-parser: a GR byte in a DCS header keeps the string
- aterm-parser: a DCS header is carried as itself
- aterm-parser: the Verification section names the checks that exist
- aterm-core: an ASCII run from outside a DECSLRM span goes glyph by glyph
- aterm-grid: a cell an operation blanks drops the extras it carried
- aterm-core: REP repeats the folded character on the bulk path too
- aterm-grid: one row len rule for every writer, printed blanks included
- aterm-core: a VT52 address takes two bytes; ASCII never folds after a ZWJ
- aterm-grid: an extras run resets only an occupied slot; the ring path relies on its source
- aterm-grid: ICH and DCH on a double-width row shift its cells only as far as its extras
- aterm-grid: a rectangle scroll keeps the row's wide-character hint
- aterm-grid: an alternate-screen width cut drops the cut head's extras
- aterm-search: key postings from a per-index base so rows past u32::MAX stay findable
- aterm-search: scale the regex scan budget with the line and report a line it cannot finish
- aterm-gui: a search header names every cause of a short list, the depth cap included
- aterm-ctl: the search note is built in one String, keeping the Trust lane's proof count
- aterm-search: run-length encode the column map so a non-ASCII index holds a small multiple of its text
- aterm-search: report a match in the grid cells that hold it, read from the grid, not re-measured from the row's text
- aterm-gui: find joins a soft-wrapped run by the grid's cells, row k from column k*cols, so a hit after a VS16 base left narrow in the last column is where it is drawn
- aterm-grid: ASCII after a ZWJ opens a cell of its own when a stored line is laid out, as the live grid draws it
- aterm-messages: the presence row's tokens strip every invisible character, from one table
- aterm-messages: the presence row is laid out and painted in the terminal grid's cells
- aterm-messages: a presence cell holds what the grid's cell holds, so a token stays bounded and the walk stays linear
- aterm-core: the DCS header carry test holds under the sixel feature too
- aterm-gui: the consent_at_risk test holds the env lock while it reads HOME
- aterm-grid: a tiered grid whose store keeps nothing keeps history contiguous across resizes
- aterm-grid: a drag step during the offloaded rewrap keeps a zero-share grid's history
- aterm-grid: name where the zero-share re-attach keeps more than a ring-only grid
- aterm-grid: a width resize inside the detach window keeps history in order
- aterm-grid: the offloaded width reflow keeps the rows its resize pushes past the ring
- aterm-grid: the offloaded Native reflow rewraps a line straddling the store/ring seam whole
- aterm-grid: a history row rebuilt where a wide glyph cannot fit keeps no link or underline colour for it
- aterm-grid: a scrolled-back history row keeps a link or underline colour only on the cells its glyphs fill
- aterm-grid: a VS16 glyph the live grid kept narrow stays narrow in history, so the links after it stay on their glyphs
- aterm-control: a double-click selects the word in the cells the grid drew, across a soft wrap
- aterm-core: a web host's word and link under a cell are read from the cells the grid drew
- aterm-grid: a stored line lays a flag half into its base's cell past a mark, as the live grid draws it
- aterm-core: a history row is read, copied and found in the cells either tier draws it in
- aterm-gui: the keeper META fits at any width, and a META not sent is retried
- aterm-gui: the keeper META's version-skew record says what an older window trades, and its worst case is the widest
- aterm-gui: the keeper's META is serialized after the terminal's lock is released
- aterm-verify: a second interrupt ends an interrupted gate's grace, and no interrupt leaves a survivor
- aterm-verify: the interrupt handler's review: one SIGTERM is pinned, a nap asks for no remainder, sigaction only where its struct was read
- aterm-verify: an interrupt that lands inside a spawn takes that child too
- aterm-verify: a SIGKILL sent to a stage group is repeated until the group has stayed empty
- aterm-verify: the gate signals a process group only while it still holds the group's leader
- aterm-agent: a no-resume stop is reopened only for a holder its line can have started
- aterm-agent: a limit whose notice left the screen waits for the reset it named
- aterm-agent: a write a hold or a busy server refused is decided again, not dropped
- aterm-agent: a limit the vendor continued by itself is over, and the vendor's cancel ends its by-itself
- aterm-agent: a limit whose notice left is decided by the wall's policies whole, and by nothing with resume_limits off
- aterm-agent: a limit whose notice left is waited on across a loop's restart
- aterm-agent: the wall memory writes its row only at a reading of the wall
- harness: a kind's reason takes its article —
an edit box, nota edit box - harness: an owner's bare-tool ask rule holds the file box Claude Code draws no reason on
- harness: a box Claude Code draws for more than one tool is held under a bare ask rule on any of them
- harness: read the agent's settings chain where and as Claude Code reads it, never skipping the user's file
- aterm-agent: a person's turn at a left limit ends its wait, read off the screen's order or the transcript
- aterm-agent: a refusal that persists is journaled when it first appears and when it changes
- aterm-agent: the wait on a left limit wakes on the screen, as a wall's does
- aterm-agent, aterm-phase: a turn ends a left limit's wait only when served under THAT limit's own notice
- aterm-agent: a refusal's episode is its kind and holder, its measures dropped, and ends after a quiet spell
- aterm-phase: a wall's notice Ink wrapped in a narrow pane is read as the one line it is
- aterm-phase: the login back is read from its row's whole line, wrapped or not
- aterm-phase: a narrow pane's error-row bound counts only a notice drawn in the vendor's column, by Ink's own wrap; a reset keeps a date after its clock
- aterm-agent: the supervisor's waits count a Mac's sleep, and its acts wait for the wake's settle
- aterm-agent: the wake's settle holds every turn typed into the agent, counted from the wake
- upgrade: the live upgrade reads every Claude home its tabs' agents run under
- upgrade: a build that failed to start for a conversation is not retried for its hand resume
- upgrade: a user's home with no Claude records no longer waits the step's pass
- upgrade: an agent under another Claude home is judged by that home's model files
- upgrade: a restart on its own program keeps the stop of a build that failed to start
- relaunch: the relaunch on exit takes no build that failed to start for the conversation
- consent: the in-bundle fence judges the bundled image behind a launch symlink
- aterm-verify: only Live reaps by pid, and git_bounded kills git by pid only on a real overrun
- seamless: a successor's Commit fail-stop says which ending it took, with the pipe's read end already closed
- devtools: the window opens the Developer Tools pane once per process, even before its marker lands
- control: input into a background tab that reads nothing never parks a control lane
- spawn: OSC 52 query and Kitty file media read before the terminal lock, never inside process()
- control: a framed wait refused busy closes, never serving its body as requests
- spawn: the reads done before the terminal lock are bounded per slice
- control: a background paste a discard drops is not OK; a wheel cut short is not "nothing written"
- the merge contract's two reds on … (rounds 16-17 landed ungated)
- the merge contract's three reds on … (round 18's landings lane)
Refactors
- aterm-agent: seed_named_reset takes the open row's instant, not its age and now
Tests
- aterm-agent: reproduce the quiet upgrade resuming a conversation that has no transcript
- aterm-agent: reproduce an upgrade relaunch that ended at once reading as a stuck start-up screen
- aterm-gui: reproduce a graceful exit under relaunch = false said as the owner's limit
- aterm-agent: reproduce a relaunch that never stamps the exit of an agent its shell has not reaped
- aterm-agent: reproduce a relaunch stopped no-resume while its shell had not run its line yet
- aterm-agent: reproduce a no-resume stop that stands while its relaunched agent holds the conversation
- reproduce the host's second, false report over an upgrade whose own row asks
- aterm-agent: pin restart's guard that never resumes a conversation with no transcript
- aterm-phase: the usage-limit dialog Claude Code 2.1.295 really draws, in place of the hand-built frame (reproduction, ignored)
- aterm-phase: a footer Ink wrapped in a narrow pane, as Claude Code 2.1.295 draws it (reproduction, ignored)
- the artifact quarantine tests hold their guard until they end it
- the contended title retry is read at a fixed instant
- an idle harness host owes itself no look
- host_live times its held scenes from the host's attach
- operator_live_headless retries manage's busy refusal and parks its nexts
- control lanes judge a refusal below a known limit as a moment, under HANG
- host_live waits out an earlier claim as a hang; the badge test releases its worker once the server read it busy
- a parked operator next is started again only when a probe turned it away or it timed out
- the idle-drivers starvation loop waits out a busy moment, as the waits test does
- host_live's fake writes one cell at start, so a stale program name gets re-read
- the restart-holds-the-tab test says what ran when it fails (status, screen, launches, host log, journal, process tree)
- the zsh hang-detector test asks a longer window when zsh was slow to print its first line
- handoff: v0.103.0's producer fixtures, written by its own cut
- aterm-gui: NET-2's credential fixtures are split, as the file's others are
- aterm-cli: the job ignores SIGHUP before the seam lets its shell exit
- aterm-core: a seeded random stream is read-boundary invariant
- aterm-core: the generated corpus include carries rustfmt::skip
- aterm-verify: a stand-in gate arms on its grandchild's exec, not on the pidfile
- aterm-verify: a stand-in gate arms on the image its grandchild runs, not on its name
- aterm-verify: the spawn window's review: the wait's bound, the count's place and its lowering are pinned
- aterm-verify: a second interrupt does not end the wait for a spawn in flight: pinned; the docs name what the count costs and how long the wait is
- aterm-verify: the kill-until-gone second reading's notes: the door's order and Live's refusal are pinned, the git test ends its helper on unwind
- aterm-gui: the parent-death fixture hands its pipe over under every std, and a stand-in checks what it was handed
- aterm-gui: the parent-death fixture's review: the watcher says it still watches, the fail-stop's 74 is pinned, a handed descriptor is taken once
- aterm-agent: reproduce a hand resume after a no-resume stop reopened as the relaunch that landed (#[ignore])
- pin the block stamp, the reopen's streak, the re-arm's block and the host's agent home
- aterm-agent: a limit whose notice left the screen is continued at once (reproduction, ignored)
- aterm-agent: a continuation refused by a hold or a busy server is dropped (reproduction, ignored)
- aterm-agent: a limit the vendor continued by itself gets a usage-resume (reproduction, ignored)
- aterm-agent: a limit whose notice left passes the roster over, and is continued with resume_limits off (reproductions, ignored)
- aterm-agent: a loop restart loses the wait on a limit whose notice left (reproduction, ignored)
- aterm-agent: a fenced press a hold turned away is pressed again once it lifts
- harness: reproduce the policy sweep's pressed ask-rule boxes and its
a edit box, ignored - harness: reproduce the review's pressed Bash sed box and the settings reader's false and skipped reads, ignored
- harness: pin the Bash sed box on Claude Code 2.1.299, and record the lab's live check of the fixed harness
- aterm: the relaunch fake keeps its conversation's transcript, as Claude Code does
- aterm-agent: a person's turn at a left limit leaves its wait standing (reproductions, ignored)
- aterm-agent: a refusal that persists is journaled at every retry (reproduction, ignored)
- aterm-agent: the wait on a left limit sleeps through a person's short turn (reproduction, ignored)
- aterm-agent: the probe's left text whose Enter the server turns away is written again
- aterm-agent: a turn under another limit's notice, an unanswered prompt and another conversation's transcript end a left limit's wait (reproductions, ignored)
- aterm-agent: a refusal whose counter moves is journaled at every retry (reproduction, ignored)
- aterm-agent: the refusal episode's two ends, the remembered wall's served-turn rule and the unanswered prompt, each caught when reverted
- aterm-phase: a wall's line Ink wrapped in a narrow pane, as Claude Code 2.1.299 draws it (reproduction, ignored)
- aterm-phase: the login back, its row wrapped in a narrow pane (reproduction, ignored)
- aterm-phase: the worker's prose read as the error row in a narrow pane, and a reset's date cut off its time (reproductions, ignored)
- aterm-agent: reproduce the sleep's two residuals (ignored)
- aterm-agent: reproduce the review's sleep findings on fix/r15-sleep (ignored)
- upgrade: reproduce the sweep and the view missing an agent under another Claude home
- upgrade: reproduce a hand resume moved onto the build that failed to start for it
- handoff_rendezvous: every rendezvous test runs under a long TMPDIR, or fails saying why
- harness: reproduce the exits nobody reads — a host panic's window, a Commit's hold (ignored)
- harness: reproduce a relaunch owed at a host panic being dropped (ignored)
- harness: the switch-off control says the restart stands down (comment only)
- harness: reproduce the review's majors of round seventeen's first cut (ignored)
- harness: restate the narrowing repro by the policy each loop ran under; reproduce a switch-on that waits out the back-off (ignored)
- harness_host: reproduce the explicit restart's residuals that strand an agent
- harness_host, restart_act: reproduce the review of rulings 20-22
- harness: reproduce round eighteen's landings and exits left to nobody (ignored)
- harness: reproduce the review of round eighteen's first cut (ignored)
- harness: a panicking host's
alwaysis armed after its first panic, never before - harness: reproduce the round-18 upgradebuild review's strands and minors (ignored)
Docs
- what the harness does at a usage limit on 2.1.295, live; the narrow-box note; two doc reflows
- aterm-gui: the parent-death fixture's second reading: the CHANGELOG names both limits, two more comments are conditional on the std
- aterm-agent: the wall memory's note on a shell-less tab names the policy's rule as it is now
- aterm-phase: wrap's header names the login reader and how a message's rows are counted
- spawnfd, grep_guard: a bare Command's child inherits unflagged descriptors only on a std without SP-1
- the settings lane's amend — what the fence is now, the live runs, and what is left
- the trim's review — the inbox note says queued=1, the private-instance rules come back, the verified table lives in ATERM_DESIGN.md
Other
- style(aterm-agent): trustfmt the sweep fixes' tests
- WIP(aterm-deflake): load-proof gate tests written, A/B flip evidence and merge contract not run
- release(stamp): build scripts read cargo's run-time CARGO_MANIFEST_DIR and CARGO, never env!'s
- render: a sub-script glyph lands exactly, to a fraction of a pixel
- footer: set the facts as a line of type, the facts an even gap apart
- render: bundle Iosevka Term, selectable by name on every platform
- footer: the owner's-layout test says the facts stand three spaces' room apart, not three cells
- spec(aterm-spec): SupervisorUsageWall models a notice that leaves an idle screen, and a person's turn there
- kitty pet: a ghost is drawn as the body the user last saw, stance included
- kitty pet: an adopted look's stance eases only forward, through a restarted ramp too
- kitty pet: a ghost wears the palette its body was drawn in
- kitty pet: an adopting arriver resumes a ghost's palette only on its own surface
- spec(aterm-spec): SupervisorUsageWall lifts a limit before its named reset and resumes another conversation at a left wall; the bind walks both
- chore(upgrade): the watch names where it reads before what it reads; the sweep test says its cases
- harness_netprobe: reproduce the route reading its own settings list, not Claude Code's chain
- harness: the API route and the stored login read Claude Code's one settings chain
- harness: reproduce the readers of an agent's Claude records that miss its own home
- harness: one resolver for an agent's Claude records; every reader reads its own home
- claude_settings: reproduce the approval lane failing every chain read in a file-provider domain
- claude_settings: a document not there sets nothing; the file-provider fence is the route's alone
- claude_settings: reproduce the route's fence opening a linked worktree's git files
- claude_settings: the route's fence covers the git files the chain opens
- upgrade_models: reproduce a byte-order-marked settings.json read as no allowlist
- upgrade_models: the model reader parses settings.json as Claude Code does; the chain's claims say who its readers are
- AGENTS.md: cut the process cruft to the rules an agent needs
- primer v15: drop the ~/Developer sentence and trim the agent block
- devroot: delete the ~/Developer feature and its ceremony
- devroot: the doctor's help and a machine-apply doc drop their Spotlight claims
- update handoff: the Commit's _exit no longer cuts a control write mid-frame
- update handoff: activate the successor from focus read at the Commit's write
- update handoff: a reset on a parked session stands the Commit down
- update handoff: a reset at the Commit's write is never answered OK
- update handoff: the Commit's egress fence fails closed with no attempt
- Quit ends every tab's shell the way closing its tab does
waitandawait inboxend with their session, not at their deadline- A window's tab ends with its shell, not with the slave's last close
- Quit's document barrier re-plans before it lets the app exit
- A Quit replayed after an update rollback asks the document barrier too
- A shell's exit wakes what is parked on it from the exit edge itself
- A held pane goes on reading a job's output after its shell's exit
- fabric: SessionFabric::closed is endpoint_closed, so the lock census sees no cycle
- aterm-agent: repro: a limit met inside the own act's take window is never tracked
- aterm-agent: a wall is tracked wherever it is read, a point or not
- aterm-agent: repro: a retry the wall answers in its window is read as taken; a lost login no point decided is held silently
- aterm-agent: a wall read in an act's window answered it; a lost login no point decided is decided as the wall it left
- aterm-agent: repro: a wall read inside the own act's window is placed as a wall found sitting
- aterm-agent: a wall read inside the own act's window is placed as the act's answer, once per act and words
- harness: a host panic loses no exit its workers held; an exit nobody is handed is read as it is seen
- harness: a switch-off while the host is down stands it down at once, and never spins
- gui(harness): three Trust seals on the policy cell, its stamp and the stamp source (off-lane:
--cfg trust_seals) - aterm-agent: repro: a limit cancelled before any read after the own act is typed into
- aterm-agent: the limit a cancel left before any read answers the own act
- aterm-agent: a cancel's answer is confirmed only by a notice written since the act
- aterm-phase: left_wall's block end reads
unwrap_or(tippy); handoff: the final tree's lab run - aterm-phase: left_wall reads only a notice above the cancel
- harness: a panic's restart acts on news and holds its workers to the policy; a landed agent is watched until a pass names it
- harness: say when a landing's agent is watched until a pass names it
- harness: reproduce three homes residuals (ignored)
- harness: pin the relaunch's home hunks that passed every test reverted alone
- harness: an empty CLAUDE_CONFIG_DIR's profile is $HOME/.claude.json
- harness: the model list grows from the home an agent is judged under
- harness: the CLI's sweep finds Claude homes from every instance's tabs
- harness: reproduce a relative home's readers losing an agent that changed directory (ignored)
- harness: a running agent's relative home resolves where it filed its record
- harness: a unit test's sweep never dials the machine's instances
- harness: reproduce the review of fix/r17-homes2 (ignored)
- harness: a recorded home keeps the profile it keeps apart; a live leader's read comes first
- harness: the wall's tail is the transcript its agent writes now
- harness: the CLI's sweep waits on no tab it only learned homes from
- harness: another home's list growth is its own agents' alone
- harness: a look at an agent that left its record waits, asking nothing
- harness: the instances a pass with no roster reads are a field, not a cfg(test) arm
- harness: the relaunch's roster reads records as every reader does; two wordings corrected
- harness: carry an asked exit through a hand; the act's KILL reads its stamp on disk and waits for its reader
- harness: a carry asks the claim at every look; it waits on the line's own hands; take_if judges a stamp in place
- harness: a watch disarmed while it waited for the end reads nothing at that end
- spec(harness): HarnessCommitOwed models round eighteen's landings and the restart's panic
- harness: round eighteen's landings and exits are no longer left to nobody
- harness: the handoff's read of what a tab is owed carries the cause; the snapshot-only view is the tests'
- harness: the restored landing's late read asks the live list by contains (tippy)
- aterm-agent: repro: a cancel's limit answering a person's turn, the same reset, or a resumed older limit
- aterm-agent: the limit a cancel left answers any turn asked since the last look; the transcript tells the same reset; an undated one stays within a session window
- agents: cut AGENTS.md, the CLAUDE.md primer and the four skills to what an agent acts on
- agents: the primer says who types
keep going; cut more cruft from AGENTS.md and the skills - supervise-agent: a worker's private instance keeps the real HOME, so its login persists
- agents: the CHANGELOG counts against 0.103.0; the primer says when ATERM-TASK-DONE is due
- build cache: Rust intermediates go where Spotlight never looks, decided per command
- build cache: braces, symlinks and Trust's verified lane are left alone; the sweep uses the shared gone rule
- build cache: the sweep reads a build with a target, skips a running build and follows no link below $HOME
- build cache: the reclaim tests make links, so they build on unix only
- harness: the explicit restart's cause rides the handoff layout alone, never a durable one
- harness: the restored queue keeps its attempt for a landing no read reaches
- harness:
relaunch = falsedoes not refuse the explicit restart's carried relaunch - harness: a panic inside the host's restart is tested; no "exactly once" rests on a sleep
- harness: reproduce the upgrade's three round-18 residuals (ignored)
- harness: a build that failed to start is the build's fact; no agent is moved onto it until it is proved to start
- harness: the upgrade's model rule reads an agent's settings through the one chain
- harness: one resolver of a Claude home for every reader: an unset one is the agent's own HOME's, the footer's included
- harness: a build that fails to start strands no agent the upgrade asked; the stop taken back, the owner's --now, the record's own argv
Source release. SHA256SUMS is a per-file manifest of the released tree, with a detached Ed25519 signature (SHA256SUMS.sig) by a machine key named in the attached master-signed roster (aterm-machines.toml + .sig). Verification chain and key inventory: SIGNING.md in the publication engine; the roster pin is committed in aterm crates/aterm-update-core/src/pins.rs.