24 KiB
Termind Refactoring Backlog
English-only completed-work index. All entries below are closed per owner confirmation, including formerly stale implementation/verification statuses. This consolidation does not claim new test runs or retroactive full-suite passes; detailed evidence and execution logs remain in Git history. Current invariants live in ARCHITECTURE.md.
For new work: confirm references with rg, record evidence/action/net production estimate, implement one independent
change, run risk-appropriate checks, then append status/verification. Retain completed entries; count tests separately
and label structural changes without a reduction claim. Preserve frozen schemas, native lifetimes and platform adapters.
Completed items
2026-08-30 to 2026-09-04 — original IDs
- Legacy transcript: removed unreachable SwiftUI trees; retained live timestamp/risk components.
- List hosting: shared
HostingListRow/HostingListContent; retained list-specific lifecycles. - SSH initializers: consolidated private initialization, preserving temporary Hosts.
- Terminal appearance: SSH/Serial share
TerminalViewState.applyAppearance. - SFTP overloads: removed four redundant
TransferLibraryModelforwarders. - Jump Host builder: reused
sshJumpConfigurations, retaining validation/errors. - Connection interaction: shared trust/progress/prompt/reconnect policy; transport teardown remains local.
- Text collectors: shared streamed text/tool rejection for commands, titles and compaction.
- Provider authorization: shared auth/ephemeral sessions; preserved Vertex/empty-secret rules.
- SwiftData transactions: shared narrow commit helper; retained two-stage history writes.
- libssh2 continuations: shared Exec/SFTP serial-worker bridges.
- Transcript helpers: removed dead streaming/edit-binding/activity helpers.
- Composer access: callers use
conversation.composer; attachment hooks retained. - Toolbar search: removed unreachable menu/delegate/find plumbing; query/keyboard behavior retained.
- Agent SSH prompts: one typed authentication request supplies Journey/passphrase projections.
- Atomic SFTP writes: shared temp/cleanup/rename/progress, keeping source loops distinct.
- Transfer conflicts: shared Keep Both/directory/file policy, retaining distinct jobs.
- Client leases: shared acquisition/conditional disconnect, retaining reservation state.
- Legacy tool metadata: one compatibility table with generic MCP fallback.
- Presentation actions: removed unused automatic-message/action-kind duplication.
- Tool inputs: shared object/array unpacking, keeping field presenters local.
- Idle sweepers: shared
AgentIdleSweeper; callers own registries/emptiness. - Sidebar headers: shared count/collapse header.
- Host deletion: groups use repository/outbox saga, not direct snapshot deletion.
- Unused declarations: removed reference-confirmed preflight/settings/metrics/reconnect/SSH wrappers/constants.
- Settings pages: reused
SettingsFormPage, deleted duplicate page. - Cursor lists: shared fixed-height chooser adapter; specialized rows excluded.
- Agent authentication: shared typed Exec/SFTP authenticated-open retry loop.
- Transcript confirmation: shared native-row risk color/destructive confirmation.
- Glass shapes: shared private shape modifier, unchanged public behavior.
- Vault envelopes: shared record indexing; versions/merge rules remain caller-owned.
- Remote preflight: shared directory order/descendant skip/target lookup; jobs remain distinct.
- Vertex selection: shared endpoint/credential selection, subsequently adapted to API formats.
- Dead fields: removed unused onboarding/Agent/color/trial/runtime fields; retained JSON provenance.
- Run presentation: derive state from reported runs/outstanding queues.
- Copy-only tests: removed 20 tests/literals; retained behavioral/persistence/language/protocol coverage.
- Provider HTTP: shared transport/status validation; requests/parsing remain local.
- Finder drop wrapper: removed unconstructed wrapper, retained general target/test injection.
- Context Chip recovery: shared payload boundaries/fallback filenames for live/restored attachments.
- Save/rollback: reused save/commit helpers without changing transaction boundaries.
- Overlay chrome: shared transient surface; content/transitions remain local.
- SSH form chrome: shared styling, not form behavior.
- Snippet content: shared card/drag-ghost content, separate interaction/chrome.
- SFTP reads: shared remote read-handle lifetime; loops/destinations remain distinct.
- Chooser selection: shared all-checked/toggle-all for equal eligibility sets only.
- AgentKit extraction: moved portable runtime behind host/interaction/prompt/presentation seams.
- Workspace commands: removed AppKit-shadowed commands; split shortcuts avoid system keys.
- Provider addressing: one URL plus
ModelAPIFormat; migrated safely with AgentKit 0.4.0/0.5.0.
2026-09-09 to 2026-09-14
- 09-09 StoreKit trials: replaced local HMAC/Keychain/CloudKit trial with transaction watermark (−121 production lines).
- 09-09 Show Recents: removed unread setting/UI/labels; retained Sidebar accessibility localization.
- 09-11 Test cleanup: removed five redundant tests/literal snapshots (−77 test lines), retaining behavior.
- 09-11 Screenshot window: production WindowGroup replaces demo-only window; demo restoration stays off.
- 09-11 SFTP permissions: shared Domain draft/Presentation grid.
- 09-11 Persistence/sync: moved CloudKit/settings/journals/terminal/history to frameworks; desktop adapters retained.
- 09-11 Metrics/Journey: shared Application state/Presentation content; native keyboard/logs retained.
- 09-11 Skills/settings: shared library/importer/role form, retaining native editors.
- 09-12 Assistant: shared runtime/tools/attachments/speech/conversation/list behavior.
- 09-12 Aliases: removed 86 files, 224 app and 20 Persistence aliases; retained six responsibility-named adapters.
- 09-12 Mobile layers: separated TFI layers/shared connection construction; later adaptive navigation supersedes idiom policy.
- 09-12 Command generation: shared draft/coordinator/timeout/cancellation/protocol constants.
- 09-12 SFTP boundary: Domain
RemoteFile, ApplicationRemoteFileSystem/mobile session model; structural, not a reduction. - 09-12 Connection recovery: mobile adopts shared trust/progress/temporary-key preparation.
- 09-12 Terminal Find: shared controller; platform binding closures retained.
- 09-12 Linux detection: one Domain classifier distinguishes unavailable/conclusive results.
- 09-12 Journey content: shared header/status; native logs/failures/backgrounds/keyboard retained (−98 production lines).
- 09-12 Terminal themes: Presentation owns Ghostty conversion; desktop preference storage retained.
- 09-12 Terminal uploads: shared readiness/notices; execution remains platform-specific.
- 09-12 Known Hosts: shared hashed/endpoint titles; native cards retained.
- 09-12 Native lists: removed eight Mac adapters/eleven mounts (−611 lines); retained justified UIKit uses.
- 09-12 Transcript: shared tools/results/disclosures/timestamps/Markdown; native renderers/viewport lifetimes retained.
- 09-12 Dead code: removed Periphery-confirmed imports/files/declarations (−150 production lines); dynamic entries retained.
- 09-12 Test boundaries: removed concrete renderer/list-type assertions; retained behavior/identity/reuse/interaction coverage.
- 09-13 Localizations: removed 81 compiler-confirmed unused entries, stale metadata and three obsolete expectations.
- 09-13 Slash commands: shared
ChatSlashCommandRegistrywith explicit platform actions. - 09-13 Feature registry: one app-injected mobile tab/sidebar/destination registry.
- 09-13 Value policies: shared tree/route/deletion/display/Snippet/model/SFTP-drag/service policy, not native lifetimes.
- 09-13 Annual offers: StoreKit metadata replaces new standalone trials; legacy entitlement removed next.
- 09-13 Tests: removed source/Keychain/status/permission/history duplication; shared contracts moved to FrameworkTests (−1,303 lines).
- 09-14 Legacy trial: removed remaining standalone-trial product/domain/clock/UI/tests/copy; lifetime and annual trials retained.
2026-09-16 to 2026-09-17 — planners, tests and skills
- Desktop download planner: adopted shared traversal/conflicts/scoped destinations/enqueueing, including directory-only trees; desktop pending/error/lifetime ownership retained (−167 production lines).
- Desktop copy planner: adopted shared preparation/conflicts/enqueueing/mutation counts; preserved recursive deletion/cancellation/ refresh. Removed duplicate literal assertions while adding conflict regressions (−193 production, −59 old test lines).
- UI/source assertions: removed 52 declarations/1,230 lines; source checks narrowed 43→9 ownership/dependency guards with fail-closed roots/native-list allowlist. Behavioral/language/protocol/screenshot coverage retained.
- SFTP status labels: shared direction-specific running/completed presentation, generic other states (−8 production lines).
- Forwarding adapter: desktop uses shared editor policy directly, preserving saved/runtime/intent locks (−27 production lines).
- Five iOS tests: aligned no-model send failures, stable
terminal_suggestdescriptors and indexed SSH import with production behavior; retained all identifiers/no skips. Recorded verification: three independent focused actions, TFI 433/433 and TFM 1,399/1,399. - Skill loader:
skill_read_filereplaces executableload_skill; historical replay/presenter retained. Package management is additive. - Skill starters: replaced seeded runbooks/Reset with immutable runtime helpers; existing starters remain ordinary user records; conflict repair/atomic install/sync retained. Published AgentKit 0.13.0; no overall reduction claim.
2026-09-17 to 2026-09-19 — reuse scan IDs
Scan covered 516 production Swift files and framework imports; no prohibited edge found at discovery. File size alone
never justifies extraction. Keep schemas, native lists/terminal teardown and local RuntimeVersions adapters separate.
- R1 — CloudKit record coding: shared secure fields, payload/hash/asset mechanics and namespaces; coordinators retain metadata, validation/quarantine/legacy Guardian handling, 700,000-byte threshold and independent cleanup/lifetimes (−40 production lines).
- R2 — Upload/copy conflicts: shared resolver; upload retains strict-descendant versus copy's self-or-descendant policy and gains cancellation/recursive-name/path validation. Jobs/UI/accounting/errors remain separate (−139 production lines).
- R3 — Pro offers: value-only projection of StoreKit values/eligibility/plan; native layouts/actions/localization injection and History formatting remain separate (−32 production lines). R1–R3 total: −211 production lines, excluding tests/docs.
- R4 — Architecture guards: structural guard work closed per owner confirmation; retain fail-closed roots, dependency/ownership checks and native-list allowlist, not UI/copy/layout snapshots. No production-reduction or fresh verification claim.
- R5 — CloudKit lifecycle: one typed
CloudSyncLifecycleinstance/category with injected transport; zones/accounts/journals/engines/ merge/acknowledgements remain independent. Secret upload needs current-engine fetch; pause/retirement revokes authorization. - R6 — MCP ticket policy: shared metadata/expiry/retention/limits, not directional state machines. Preserve four slots, ten-minute capabilities, 64 unfinished and 256 terminal records/direction, thirty-minute retention, cleanup-held slots and Range-after-success.
2026-09-18 to 2026-09-19 — windows, mobile and authentication
- Width-based mobile layouts: removed idiom environment/duplicate root; subsequent stable adaptive tabs replace shell reconstruction.
- Window registration: apply native full-size content style before registration; removed extra bridge (−25 production lines). Normal/fullscreen/restored sizing remains window-owned.
- Metrics clocks/knowledge cards: tests await sampling/maintenance readiness; compact details use natural height within scaled caps. Production Metrics unchanged; short/long expansion and native width behavior retained.
- Adaptive navigation: one sidebar-adaptable TabView/five stable stacks replaces root reconstruction/reset/save gates; preserve drafts, search/scroll/window independence and live session instances (−210 production lines).
- Close/quit confirmations: rejected removal, restored both dialogs/strings. The final change clears only
isDocumentEditeddecoration; dismissal delegate, Workspace confirmation and SFTP unsaved-edit checks remain. Visual correction, not a reduction claim. - Free Workspace composition: removed 15 gates/window commerce/sticky grant state; aligned app/site/StoreKit copy (−34 production lines, two strings). Sync/other Pro gates remain; App Store Connect metadata is still a separate release operation.
- Desktop authentication: shared submission/Identity reuse on
RemoteSessionHostStore; preserve Identity-before-Host writes, explicit secrets, validation, temporary Hosts and native retry/prompt lifetimes (−47 production lines). - Mobile toolbar: removed Assistant/Metrics fallback reads; one shared policy retains geometry/reserved regions/native identity/OS checks.
- Batch Startup: Connect/Return is the sole confirmation, creating one new Workspace for selected SSH/SFTP Hosts; removed secondary button/policy/help/three strings (−53 chooser lines). Host-context-menu BatchLayout remains.
- Port Forwarding: removed unused wrappers/overload, narrowed picker/editor policy and shared typed managed-card deletion/error chrome with Known Hosts (−35 production, −73 test lines). Kept generation/task/Journey dictionaries: merging adds state without reduction. Forwarding pumps/authentication, frozen schemas, feature transactions and native cards remain separate.
2026-09-19 — unified SSH/SFTP channel scheduling (complete)
- Evidence:
SSHExecSession,SFTPClient,SSHSessionActor,SSHRoutedSocketandSSHForwardingSessioneach own a libssh2 session/queue/pump. Agent pooling separates exec/SFTP andsftp_copyadds two dedicated connections; user transfers fall back from an additional connection to serialized use of the browser client. These owners duplicate connection teardown/keepalive/EAGAIN rules and prevent same-transport Channel concurrency outside forwarding. - Action: extract one authenticated transport/Channel owner and two topology policies: Channel-only and
connection-preferred with Channel fallback. Agent SSH uses Channel-only; Agent SFTP (including
sftp_copy) and user transfers use connection-preferred; Port Forwarding uses Channel-only. Single-Channel consumers reuse the transport core without entering the scheduler. Feature domains retain independent authentication/recovery/lifetimes. - Expected reduction: remove the dedicated Agent-copy lease path and duplicated exec/SFTP/PTY/forwarding pump and teardown code. Record the measured production-line change and focused/full verification only after the migration is complete; no reduction or performance claim is made while this item is in progress.
- Result: added explicit Channel-only/connection-preferred policies, multiplexed Agent exec, pooled Agent SFTP (including copy and MCP streams), sibling-Channel fallback, lease-based limits and a single-Channel Adapter for Metrics/ user SSH. Removed the old exec worker, dedicated-copy leases, whole-session background handoff and blocking key export. This capability is additive: tracked production changed +987/−931 lines and three new core files add 628 lines, net +684; no reduction claim.
- Verification: TFM and generic iOS Simulator builds passed; 99 scheduling/auth/forwarding focused tests, 53 SFTP/
PTY/key tests, 13 pool/Adapter tests and the 20-test AgentRuntime suite passed. Chinese localization and changed-file
strict format checks passed. The full macOS run reached 1,446 TFM and 363 Framework tests but retained the unrelated,
reproducible
LaunchFileLogServiceTests.loggerDropsUnapprovedSensitiveValuesfailure; one concurrent AgentRuntime cancellation failure passed immediately when its 20-test suite was rerun. Recursive format also retains the unrelated existingLoggingFilesSettings.swift:110finding.
2026-09-19 — fair SFTP admission and selectable topology (complete)
- Evidence: the app transfer coordinator admitted the first eligible queued row, so one Workspace could fill every Host slot, while Agent SFTP leases bypassed the 15/5 limits entirely. User and Agent pools also fixed their topology at connection-preferred even when a small transfer would not repay another SSH handshake. Internal SFTP drag providers advertised both a private remote payload and a Finder file promise; reading both representations could start a redundant download beside the direct remote copy.
- Action: add one process scheduler shared by Workspace/terminal/edit and Agent data work, rotating Hosts and then stable Workspace/Agent-run/batch sources. Resolve Smart (64 MB decimal), Channels Only and Connections Preferred only after admission; retain feature-owned connection lifetimes and connection-to-Channel fallback. Extend the existing synced SFTP preference record compatibly and consume the private drag payload without materializing its local-file promise.
- Result: new/missing settings default to Smart and 30/10 while saved values remain unchanged. Logical file operations
consume identical capacity whether backed by a Channel or connection; cross-Host copy counts once globally and once per
endpoint. Agent control operations remain outside data capacity,
sftp_copyuses one composite permit, and in-app remote copy exposes one.copyrow per regular file without local staging. This is additive scheduling work, not a reduction claim. - Verification: macOS and generic iOS Simulator builds passed. Focused suites passed for scheduler/session topology, settings persistence/sync, Agent authentication/MCP, Agent/Workspace copy and native drag payload selection. Chinese localization and diff checks passed; final full-suite/format status is recorded in the task handoff.
2026-09-19 — shared Agent SSH/SFTP primary transport (complete)
- Evidence: Agent exec and the primary Agent SFTP client still used separate authenticated transports even though the non-blocking connection owner could host both Channel types. A first exec followed by SFTP therefore performed two handshakes, while connection-preferred SFTP concurrency correctly needed its independent auxiliary transports.
- Action: rename the exec-only session abstraction to
SSHMultiplexedSession, expose SFTP Channel creation on it, and key the Agent pool's primary entry/in-flight open by Host only. Keep SFTP admission, Smart thresholds, auxiliary connections and silent Channel fallback unchanged. - Result: exec and primary SFTP now share one authentication and physical connection in either call order. A reusable full non-blocking SFTP Channel client serves PTY and Agent owners; only scheduler-selected auxiliary SFTP work opens more transports. Host retirement, route changes and fatal primary failures close the shared lifetime atomically, without replaying operations.
- Verification: focused pool/authentication/copy tests and macOS build passed during implementation; final cross-platform, localization and format status is recorded in the task handoff.
2026-09-20 — one SFTP Channel implementation (complete)
- Evidence: the standalone
SFTPWorkerand multiplexedSSHSharedSFTPClientseparately implemented directory, atomic write, resume, edit, streaming and copy semantics, while the Agent and terminal workers duplicated SFTP Channel ownership and EAGAIN loops. The new type name also described reuse (Shared) rather than responsibility. - Action: keep
SFTPClientas the public connection facade andSSHMultiplexedSessionowner, move all file operations toSFTPChannel, and shareSSHMultiplexedSFTPChannelOwneracross standalone, Agent and terminal transports. Rename Agent pool APIs from exec-only terms tosession,connectionandsftpClient. - Result: removed the second SFTP operation engine and both feature-local Channel owners. One implementation now preserves atomic rename, partial-file verification, edit permissions/version capture, streamed download validation and same-transport copy for every entry point. Tracked production plus the two new files changed +1,523/−2,695 lines (net −1,172).
- Verification: macOS and iOS builds, 87 focused pool/auth/edit/resume/rename/copy tests, 14 opt-in loopback SSH/SFTP wire
tests and all 363 Framework tests passed. The 1,465-test TFM run retained two unrelated concurrent timing failures in
AgentRuntimeTests/MCPUploadTests; both passed together on immediate focused rerun. Changed-file strict formatting and Chinese localization checks passed; recursive formatting retains the pre-existingLoggingFilesSettings.swift:110finding.
2026-09-20 — explicit SSH connection and Channel vocabulary (complete)
- Evidence:
SSHMultiplexedSessionrepresented an authenticated reusable connection, Agent connection-pool entries were namedsession, and comments called the combined routed socket/libssh2 state a transport. Conversely, SFTP subsystem Channels and authenticated connection owners shared the word session. This made byte transport, libssh2's historicalLIBSSH2_SESSIONhandle name, authenticated connection ownership andLIBSSH2_CHANNELvalues indistinguishable in APIs. - Action: reserve transport for the routed byte stream, introduce
SSHAuthenticatedConnectionas the owner of that stream plus the libssh2 connection state, expose multiplexing throughSSHConnection, and use libssh2-aligned PTY/exec/SFTP Channel names. Split the SFTP connection-opening facade fromSFTPChannelProtocol; keep forwarding TCP Channels as Channels. - Result: connection pooling, retry errors, forwarding owners, Agent authentication contexts, Channel budgets, SFTP sibling
topology and file names now reflect the protocol boundary.
SFTPConcurrencyStrategy.channelsOnlyretains its existing"channels_only"raw value, so synced settings need no migration. - Verification: TFM and generic iOS Simulator builds passed. Sixty-six focused connection/Channel/SFTP tests passed; changed-file strict formatting and Chinese localization checks passed.
2026-09-20 — one-shot SSH secret ownership and connection attempts (complete)
- Evidence: runtime credentials were represented by copy-on-write
Dataafter leaving Keychain, so appending a NUL could abandon an uncleared allocation. Temporary form answers were copied asStringvalues into attempt dictionaries; five feature owners repeated password/passphrase reentry routing. Authorized-Key export resolved every selected Host's credentials eagerly and reused one one-shot configuration across several physical connections. - Action: give
SSHSecretone explicitly owned allocation; move submitted plaintext into that owner before an attempt; centralize route reentry selection; narrow connection-time secret resolution; query Keychain existence without reading values; fail closed on malformed legacy private-Key envelopes; authenticate once per Host for multi-Key export. - Result: source
Data, proxy frames and one-shot allocations are cleared through oneSecretMemoryboundary. Retry state retains only selection metadata and reentry flags, while attempt copies share invalidating secret owners. The session host port no longer exposes its legacy plaintext credential reads. Export preparations contain references only, resolve immediately before work and open one connection with sequential exec Channels for all selected Keys. This is a safety/ownership refactor; no production-line reduction is claimed. - Verification: macOS and generic iOS Simulator builds passed. Fifty-three focused authentication, Agent and authorized-Key tests passed; all 381 Framework tests passed. The default macOS run finished with 1,792 passed, 64 opt-in skips and no failures. Changed-file strict formatting, diff checks and Chinese localization passed.