--- type: engineering quickstart title: Quickstart and task routing description: Start here to route Termind changes to their owners, preserve platform lifetimes and dependency pins, and choose focused build and test gates. tags: [engineering, architecture, routing, testing, macos, ios] sources: - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md - id: openwiki-source-1635d0be12e44ef9134ffabc resource: repo://Frameworks/TermindApplication/Connections/ConnectionJourney.swift - id: openwiki-source-1d1f503a260f304a969fcee4 resource: repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift - id: openwiki-source-131881b779429a1d1d605e52 resource: repo://Frameworks/TermindPresentation/ConnectionJourneyRouteView.swift - id: openwiki-source-d2d4c06f734241db3badc1f5 resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift - id: openwiki-source-bf7a64e7c819eb9279e2f9e4 resource: repo://FrameworkTests/CloudSyncLifecycleTests.swift - id: openwiki-source-db40aa993661b07f1a9aff6d resource: repo://FrameworkTests/SSHInteractionPolicyTests.swift - id: openwiki-source-eaed8c88a9a3f24e3feb1f9c resource: repo://FrameworkTests/WebAuthnVaultMetadataTests.swift - id: openwiki-source-9e7915b5fd54b91e430607e2 resource: repo://libghostty-spm/Sources/GhosttyTerminal/Platform/UIKit/UITerminalView.swift - id: openwiki-source-cd0be716a2446029f345525a resource: repo://Termind.xcodeproj/project.pbxproj - id: openwiki-source-105d05d558f14996921a83f6 resource: repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift - id: openwiki-source-e43a0da5ab77c2fc3554244d resource: repo://TFI/App/MobileSceneModel.swift - id: openwiki-source-5b8c72c5373a41af34fa9fd4 resource: repo://TFI/App/MobileStartupView.swift - id: openwiki-source-c1f5a86747a33d4e8472672c resource: repo://TFI/App/MobileWorkspaceSessionModel.swift - id: openwiki-source-6c9f797fc6a1e7ce639b72b8 resource: repo://TFI/App/TermindIOSApp.swift - id: openwiki-source-ca0b3e6e839587396cdeaf54 resource: repo://TFI/Platform/MobileTerminalSurface.swift - id: openwiki-source-707053bb7defcfbf9343584b resource: repo://TFI/UI/Components/MobileConnectionJourneyView.swift - id: openwiki-source-fffc181d864b6caea779a6f5 resource: repo://TFITests/MobileAdaptiveLayoutTests.swift - id: openwiki-source-b822b041afbf829d09a8555a resource: repo://TFITests/MobileAppTests.swift - id: openwiki-source-5f3340557a76d700b8808d40 resource: repo://TFITests/MobileConnectionJourneyRenderingTests.swift - id: openwiki-source-7341d7b266d976d7aac5d161 resource: repo://TFITests/MobileEditorToolbarTests.swift - id: openwiki-source-2c7245a9a1462a5a8d09b739 resource: repo://TFITests/MobileMetricsJourneyTests.swift - id: openwiki-source-b360f8803ec98b554faad9bb resource: repo://TFITests/MobileWorkspaceSessionTests.swift - id: openwiki-source-4dbea0ff2808163cb4ecdd8f resource: repo://TFM/App/AppModel.swift - id: openwiki-source-873894299539cce9a737a860 resource: repo://TFM/App/RootView.swift - id: openwiki-source-6570374eaac2e0278fa84640 resource: repo://TFM/App/TermindApp.swift - id: openwiki-source-fe5539ed6f675410b82b41c4 resource: repo://TFM/Features/Terminal/PersistentTerminalSurfaceView.swift - id: openwiki-source-dc041600497a72c229d5eef4 resource: repo://TFM/UI/Components/ConnectionJourneyView.swift - id: openwiki-source-73c75477db0674192248aa00 resource: repo://TFMTests/AppTerminationTests.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift - id: openwiki-source-85c3f954351f96433cb1fb4b resource: repo://TFMTests/ConnectionJourneyTests.swift - id: openwiki-source-c7d015a20982da4e8b0599d1 resource: repo://TFMTests/MetricsJourneyRenderingTests.swift - id: openwiki-source-0dd012e3740bcc348fc36ccb resource: repo://TFMTests/StoreKitTrialTests.swift - id: openwiki-source-a08489338be00125d646c77e resource: repo://TFMTests/VisibleWindowTestTrait.swift - id: openwiki-source-402244fee941f965f41388e4 resource: repo://TFMTests/WebAuthnSSHTests.swift generated: { by: "codex", at: "2026-10-02T08:42:40.505Z" } verified: - by: openwiki/0.6.0 at: 2026-10-02T08:42:40.505Z --- # Quickstart and task routing Termind is one Xcode project with native `TFM` (macOS) and `TFI` (iPhone/iPad) app targets over shared frameworks, plus separate test, widget, and macOS MCP bridge products; platform UI and lifecycle remain app-owned. Source and tests are authoritative. Before changing an ownership boundary, read [Cross-Cutting Engineering Invariants](/openwiki/architecture/engineering-invariants.md) and the narrowest topic page below. ## Find the owner | Change | Route and focused check | | --- | --- | | Module placement, imports, nested directories, or shared resources | [Module and Product Map](/openwiki/architecture/module-map.md), [Dependency and Ownership Boundaries](/openwiki/architecture/system-boundaries.md), [Shared Framework Responsibilities](/openwiki/architecture/shared-module-directories.md), [Native App Responsibilities](/openwiki/architecture/native-app-directories.md), and [Supporting Products and Tooling](/openwiki/architecture/supporting-system-directories.md); run `ArchitectureBoundaryTests` for dependency changes. | | Composition, startup failure, window/scene state, backgrounding, quit | [Platform Composition and Lifetimes](/openwiki/architecture/platform-runtime.md); use `AppTerminationTests`, `MobileAppTests`, `MobileWorkspaceSessionTests`, or `MobileForwardingLifecycleTests` for the changed lifetime. | | Desktop Navigator, sidebar, workspaces, Vault, Assistant layout | [macOS UI and Workspace Ownership](/openwiki/architecture/desktop-ui.md); target window/navigation or layout tests. | | Desktop Workspace/Pane sorting, merging, drag-out new windows, or Assistant list reordering | [TFM Drag and Drop](/openwiki/workflows/desktop-drag-and-drop.md); preserve the native Workspace List source and live receiver contracts. Use `WorkspaceNavigatorDropTests`, `WorkspaceLayoutDropTests`, `WorkspaceWindowMoveTests` or `AssistantConversationListDropTests`, plus the source/cancellation/animation suites listed in that guide. | | File-drop events, Assistant attachments, SSH terminal/SFTP uploads, desktop remote-file dragging or Key import | [File Drag and Drop Across TFM and TFI](/openwiki/workflows/file-drag-and-drop.md); trace native routing, payload priority, provider staging and transfer lifetimes. Use `FileURLDropTargetTests`, `MobileDropTests`, upload/attachment/import suites listed there; the guide also locates the shared Overlay UI. | | Mobile tabs, scene routes, cards, editors, terminal continuity | [iOS and iPadOS UI and Scene Ownership](/openwiki/architecture/mobile-ui.md); use `MobileWorkspaceSessionTests` for window-owned connection/routing changes, `MobileAdaptiveLayoutTests` or `MobileNavigationParityTests` for UI changes. For native metrics authentication/navigation use `MobileMetricsJourneyTests`. | | Shared UI conventions, fields, tokens, accessibility | [UI Design and Shared Presentation](/openwiki/concepts/ui-design-principles.md); check platform renderings and `ArchitectureBoundaryTests`. | | SSH/Telnet, credentials, routes, host-key trust, session cleanup | [SSH, Telnet, Trust, and Workspace Session Lifecycle](/openwiki/workflows/ssh-session-lifecycle.md); run connection, trust, authentication, and session tests. For journey route/checkpoint changes, `ConnectionJourneyTests` covers shared state and `MobileConnectionJourneyRenderingTests` covers native mobile rendering; see [Behavioral Tests and Fixtures](/openwiki/testing/behavioral-boundaries-and-fixtures.md). For channel admission and backpressure see [SSH Multiplexing and I/O Scheduling](/openwiki/concepts/ssh-multiplexing-and-scheduling.md). | | SSH Security Key registration, FIDO2/WebAuthn signing, Vault metadata, or forwarding limits | [SSH Security Key Authentication](/openwiki/concepts/ssh-security-key-authentication.md); use `FrameworkTests/WebAuthnVaultMetadataTests.swift` for destination/jump resolution without Keychain, V45/V2 Vault metadata, legacy storage normalization and failure rollback; `TFMTests/WebAuthnSSHTests.swift` for assertion/registration validation and SSH wire fields; and `FrameworkTests/SSHInteractionPolicyTests.swift` for silent-connection restrictions. These fixtures do not replace a hardware-key and native-prompt check. | | Terminal, metrics, forwards, shell hooks or forwarding pools | [Remote Services and Forwarding](/openwiki/concepts/remote-services-and-forwarding.md), [Shell Integration](/openwiki/concepts/shell-integration.md), [Port Forwarding Dispatch](/openwiki/workflows/port-forwarding-pool-and-dispatch.md); choose the matching service or pump tests. For metrics keyboard-auth presentation, use `MetricsJourneyRenderingTests` on desktop and `MobileMetricsJourneyTests` on mobile. | | Ghostty terminal menus, touch selection, native surface identity, themes or highlighting | [Ghostty Terminal Integration](/openwiki/concepts/ghostty-terminal-integration.md); for menu changes inspect both iOS touch hooks and the separate pointer path, plus macOS secondary-click composition. Run `TerminalContextMenuTests` and `MobileTerminalUploadMenuTests`; use the fork touch-selection tests when its menu seam changes. | | Ghostty fork source, Swift menu hooks, native patches, XCFramework or dependency pin | [Ghostty Fork Maintenance](/openwiki/operations/ghostty-fork-maintenance.md); keep the pushed fork revision, submodule gitlink, project revision and resolved pin aligned, and publish a new XCFramework asset first for native patch changes. | | SFTP browsing, transfer scheduling, external edit | [SFTP Transfer, Scheduling, and External Edit Workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md); select the transfer, conflict, or edit suite. | | Assistant turns, approvals, host tools, skills, memory | [Assistant and Agent Runtime](/openwiki/concepts/agent-runtime-and-assistant.md); target preparation, cancellation, persistence, tools, or memory tests. | | SwiftData, secrets, migrations, CloudKit, settings | [Persistent Data, Migrations, and Secrets](/openwiki/concepts/persistence-and-secrets.md), [Settings, Vault, Metrics, History, Device, and Cloud Sync](/openwiki/workflows/settings-and-cloud-sync.md), and [CloudKit Release Readiness](/openwiki/operations/cloudkit-release-readiness.md); select repository, migration, or `CloudSyncLifecycleTests` / `CloudSyncSafetyTests` for a sync lifecycle change. | | MCP server, external upload/download, bridge | [MCP Server, Transfers, and Stdio Bridge](/openwiki/integrations/mcp-server-and-bridge.md); run token, server-session, transfer, or bridge tests. | | StoreKit, localized copy, widgets, screenshots, website | [Commerce, Localization, and Product Surfaces](/openwiki/concepts/commerce-localization-and-product-surfaces.md), [Storefront Commerce Release Checks](/openwiki/operations/storefront-commerce-release.md), [Marketing Assets and App Icons](/openwiki/operations/marketing-assets-and-app-icons.md), and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md); use catalog normalization and bilingual validation, app/language, screenshot, StoreKit, or website checks as appropriate. | | Picking a deterministic test seam | [Behavioral Tests and Fixtures](/openwiki/testing/behavioral-boundaries-and-fixtures.md); run the narrow behavioral test before the affected target suite. | ## Lifetime and change boundaries `TermindDomain` defines portable rules; `TermindApplication` owns ports and use cases; `TermindPersistence` owns SwiftData models, repositories and container construction; infrastructure implements services; `TermindPresentation` owns reusable SwiftUI content and copy; apps assemble concrete dependencies and native UI. `ArchitectureBoundaryTests` checks **specific** forbidden imports per root, not an all-UI-framework ban: its five-framework rule excludes Presentation and rejects app targets plus `AppKit`, `UIKit`, `IOKit` and `ServiceManagement`; the separate Presentation rule allows `SwiftUI` but rejects app targets, `AppKit`/`UIKit`, storage, concrete infrastructure and `StoreKit`. Shared Application cannot import Infrastructure, Persistence or SwiftData; desktop Application/Features and mobile layers have their own checks. The tests also guard concrete constructions in selected feature/application roots, AgentKit type duplication and SwiftData ownership. Fix an ownership violation rather than bypassing the test; see [Dependency and Ownership Boundaries](/openwiki/architecture/system-boundaries.md) for the precise scope. `TermindApp` makes the macOS container and shared `AppModel` at launch; XCTest and debug screenshot demos use in-memory stores. If the local database cannot open, startup fails rather than replacing it with an empty store. Each main `WindowGroup` instance gets its own `WindowModel` for selection and workspaces while app services are shared; `RootView` registers the window, installs its focused scene value and keeps mounted workspace views when switching destinations. The separate external-authentication `Window` shares the app environment, but removes its manual Window-menu command; it is not another main workspace. `TermindIOSApp` migrates language preferences and creates one live or testing `MobileAppModel`; `MobileStartupView` injects its container on success and shows unavailable data on failure. `MobileStartupView` waits for the native scene delegate's session ID; `MobileBoundSceneRoot` then creates a `MobileSceneModel` in a task, retaining it for that persistent UIKit session rather than constructing observable state during view evaluation. The scene delegate binds to the shared app on appearance; the scene owns navigation and an Assistant presentation model, while its `MobileWorkspaceSessionModel` owns that window's live workspaces and saved descriptors. The app model aggregates shared services and sessions, **not one interchangeable workspace pool across windows**. Cold launch consolidates saved descriptors into the first bound session without connecting; selecting one publishes its workspace in that owner's session before connecting. A link received in another window activates the owner rather than making another connection. If a native session truly disappears, reconciliation can transfer its live workspace to an active session without reconnecting; explicit discard closes the affected workspace. Do not persist transports, secrets, one-shot commands or initial paths in descriptors. Desktop session/pane and mobile workspace owners end their own connection-history entries on close. See [iOS and iPadOS UI and Scene Ownership](/openwiki/architecture/mobile-ui.md) and [SSH, Telnet, Trust, and Workspace Session Lifecycle](/openwiki/workflows/ssh-session-lifecycle.md). In Debug XCTest runs, the **real desktop app** still launches. By default it suppresses automatic launch of the main and external-auth scenes and disables main-scene restoration; an explicit `TERMIND_WINDOW_TESTS=1` lifts suppression, as does an active screenshot demo. This host-level safeguard complements, rather than replaces, `.requiresVisibleWindow` on any test that presents a window or takes focus. Screenshot demos also disable main-scene restoration. See [Behavioral Tests and Fixtures](/openwiki/testing/behavioral-boundaries-and-fixtures.md) and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md). Mobile phase changes are aggregated across scenes: background work is paused when *all* registered scenes are backgrounded; the expiration handler suspends workspaces, stops forwards, pauses transfers, and expires Assistant work. An active scene resumes monitoring, memory, workspaces, eligible sync, and metrics. On macOS, closing the last window does **not** always quit: during tests it never terminates the test host; otherwise the menu-bar metrics preference and running metrics decide. Quit first rechecks unuploaded SFTP edits and can be cancelled; confirmed termination fences new Assistant runs, drains cancellation/persistence, stops transfers and MCP, then closes agent resources. The delegate replies to AppKit only once, after cleanup or a three-second fallback; the fallback bounds the quit reply, not completion of asynchronous cleanup. Use [Platform Composition and Lifetimes](/openwiki/architecture/platform-runtime.md) for the full sequence and ownership rules. AgentKit is a separately versioned, host-neutral remote package for the agent loop, approvals, providers, MCP client and built-in tools; Termind owns SSH/SFTP tools and registers them additively. The Xcode project currently requires AgentKit `0.18.1` or later within the next major version; `Package.resolved` records the selected remote release and revision. For a cross-repository change, test and release `../AgentKit`, then update `minimumVersion` in `Termind.xcodeproj/project.pbxproj` **and** re-resolve `Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved`; the sibling working tree does not affect Xcode's resolved build. Ghostty has a different release boundary: `libghostty-spm/` is a maintenance submodule, but Xcode consumes the remote fork at a fixed revision, not that checkout. For package changes push the fork, then update the submodule gitlink, project revision and resolved pin together; native patch changes additionally require a new XCFramework release and matching package URL/checksum. See [Ghostty Fork Maintenance](/openwiki/operations/ghostty-fork-maintenance.md) for the exact fork sequence and [Ghostty Terminal Integration](/openwiki/concepts/ghostty-terminal-integration.md) for the native menu hooks. Keep metadata in persistence and secret values behind Keychain references. Follow [Dependency and Ownership Boundaries](/openwiki/architecture/system-boundaries.md) for imports and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md) for release steps. For CloudKit changes, follow [Settings and Cloud Sync](/openwiki/workflows/settings-and-cloud-sync.md) through the [release checklist](/openwiki/operations/cloudkit-release-readiness.md): `CloudSyncLifecycle` owns a separate engine and account scope per category. It commits a recovery fence before making an automatically syncing engine, fetches before authorizing uploads, and reconciles pending engine changes against the durable journal. Pausing, account changes and non-cancellation persistence failures retire the engine and cancel its operations; late callbacks must not act on a replacement engine. Recheck `CloudSyncLifecycleTests` (including retirement and delegate-context coverage), `CloudSyncSafetyTests`, and the relevant coordinator tests rather than treating a successful build as a sync migration check. For connection-journey presentation, shared `ConnectionJourney` tracks route progress and authentication/host-key checkpoints, while `ConnectionJourneyRouteView` draws the common route; each app owns its surrounding native prompts and navigation. Test shared state with `ConnectionJourneyTests`, then the affected app's rendering or metrics-journey fixture; do not treat a rendering fixture as a live SSH test. ## Focused validation Run the nearest behavioral regression first, then the relevant product suite. Always keep `-onlyUsePackageVersionsFromResolvedFile` so ordinary builds do not silently move the resolved dependency graph: ```sh xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile build xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test xcodebuild -project Termind.xcodeproj -scheme TFI -destination 'generic/platform=iOS Simulator' -onlyUsePackageVersionsFromResolvedFile build xcrun swift-format lint --strict --recursive Frameworks TFM TFI FrameworkTests TFMTests TFITests TermindMCPBridge Scripts/check-zh-localization.sh ``` For `TFI` tests use an installed iPhone/iPad simulator; initialize `libghostty-spm/` with `git submodule update --init libghostty-spm` only if you need its maintenance checkout (routine pinned builds do not use it). Visible-window macOS suites require `.requiresVisibleWindow` and explicit `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` (or `TERMIND_WINDOW_TESTS=1` in the Xcode test action), preferably with `-only-testing:TFMTests/`; the opt-in enables both the test and automatic app-host windows. Opt-in mobile key-window suites require `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1`, `-parallel-testing-enabled NO`, and a narrow `-only-testing:TFITests/`; `MobileAdaptiveLayoutTests` and `MobileMetricsJourneyTests` are serialized but not gated by that variable; use a narrow nonparallel run when working with their process-wide UIKit window fixtures. StoreKit suites require manual authorization and `TERMIND_STOREKIT_TESTS=1`. Keep these gates off for routine checks; offscreen tests remain enabled. Define app copy via shared `TermindPresentation/Strings` resources; new app text needs completed `zh-Hans` and `zh-Hant` translations in `Frameworks/Resources/Localizable.xcstrings`. Shared catalogs are manually managed: after catalog edits run `Scripts/normalize-string-catalogs.py --write`, then `Scripts/check-appstrings.sh` and `Scripts/check-zh-localization.sh` (requires `jq`); run the Chinese check even without intended copy changes, and `AppLanguageTests` for language behavior. For web changes run `cd LandingPage && npm ci && npm run build` and check English and `/zh/` routes. Before submitting, inspect the diff for secrets, generated artifacts, cross-layer imports and accidental `Package.resolved` churn; use the routed operations pages for CloudKit deployment, StoreKit release, marketing assets, and forwarding benchmark measurement semantics.