Files
Termind/openwiki/quickstart.md
T
2026-10-01 08:45:15 +08:00

20 KiB

type, title, description, tags, verified, sources, generated
type title description tags verified sources generated
engineering quickstart Termind Engineering Quickstart Task-oriented routes to Termind's owning layer, startup and shutdown lifetimes, focused tests, and build gates.
engineering
architecture
routing
testing
macos
ios
by at
openwiki/0.5.2 2026-09-30T23:24:42.368Z
id resource
openwiki-source-8037e2358a2c4f9b2c722a11 repo://AGENTS.md
id resource
openwiki-source-1635d0be12e44ef9134ffabc repo://Frameworks/TermindApplication/Connections/ConnectionJourney.swift
id resource
openwiki-source-1d1f503a260f304a969fcee4 repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift
id resource
openwiki-source-131881b779429a1d1d605e52 repo://Frameworks/TermindPresentation/ConnectionJourneyRouteView.swift
id resource
openwiki-source-d2d4c06f734241db3badc1f5 repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift
id resource
openwiki-source-bf7a64e7c819eb9279e2f9e4 repo://FrameworkTests/CloudSyncLifecycleTests.swift
id resource
openwiki-source-db40aa993661b07f1a9aff6d repo://FrameworkTests/SSHInteractionPolicyTests.swift
id resource
openwiki-source-eaed8c88a9a3f24e3feb1f9c repo://FrameworkTests/WebAuthnVaultMetadataTests.swift
id resource
openwiki-source-cd0be716a2446029f345525a repo://Termind.xcodeproj/project.pbxproj
id resource
openwiki-source-105d05d558f14996921a83f6 repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
id resource
openwiki-source-906678adb91c2fce2d3fcaed repo://TFI/App/MobileAppModel.swift
id resource
openwiki-source-c8d832474c03f5ebad7b0578 repo://TFI/App/MobileRootView.swift
id resource
openwiki-source-e43a0da5ab77c2fc3554244d repo://TFI/App/MobileSceneModel.swift
id resource
openwiki-source-5b8c72c5373a41af34fa9fd4 repo://TFI/App/MobileStartupView.swift
id resource
openwiki-source-c1f5a86747a33d4e8472672c repo://TFI/App/MobileWorkspaceSessionModel.swift
id resource
openwiki-source-6c9f797fc6a1e7ce639b72b8 repo://TFI/App/TermindIOSApp.swift
id resource
openwiki-source-707053bb7defcfbf9343584b repo://TFI/UI/Components/MobileConnectionJourneyView.swift
id resource
openwiki-source-fffc181d864b6caea779a6f5 repo://TFITests/MobileAdaptiveLayoutTests.swift
id resource
openwiki-source-b822b041afbf829d09a8555a repo://TFITests/MobileAppTests.swift
id resource
openwiki-source-5f3340557a76d700b8808d40 repo://TFITests/MobileConnectionJourneyRenderingTests.swift
id resource
openwiki-source-7341d7b266d976d7aac5d161 repo://TFITests/MobileEditorToolbarTests.swift
id resource
openwiki-source-2c7245a9a1462a5a8d09b739 repo://TFITests/MobileMetricsJourneyTests.swift
id resource
openwiki-source-b360f8803ec98b554faad9bb repo://TFITests/MobileWorkspaceSessionTests.swift
id resource
openwiki-source-4dbea0ff2808163cb4ecdd8f repo://TFM/App/AppModel.swift
id resource
openwiki-source-873894299539cce9a737a860 repo://TFM/App/RootView.swift
id resource
openwiki-source-6570374eaac2e0278fa84640 repo://TFM/App/TermindApp.swift
id resource
openwiki-source-dc041600497a72c229d5eef4 repo://TFM/UI/Components/ConnectionJourneyView.swift
id resource
openwiki-source-73c75477db0674192248aa00 repo://TFMTests/AppTerminationTests.swift
id resource
openwiki-source-d3d065330c730839f5cc6112 repo://TFMTests/ArchitectureBoundaryTests.swift
id resource
openwiki-source-85c3f954351f96433cb1fb4b repo://TFMTests/ConnectionJourneyTests.swift
id resource
openwiki-source-c7d015a20982da4e8b0599d1 repo://TFMTests/MetricsJourneyRenderingTests.swift
id resource
openwiki-source-0dd012e3740bcc348fc36ccb repo://TFMTests/StoreKitTrialTests.swift
id resource
openwiki-source-a08489338be00125d646c77e repo://TFMTests/VisibleWindowTestTrait.swift
id resource
openwiki-source-402244fee941f965f41388e4 repo://TFMTests/WebAuthnSSHTests.swift
by at
openwiki/0.5.2 2026-09-30T23:24:42.368Z

Termind Engineering Quickstart

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 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, Dependency and Ownership Boundaries, Shared Framework Responsibilities, Native App Responsibilities, and Supporting Products and Tooling; run ArchitectureBoundaryTests for dependency changes.
Composition, startup failure, window/scene state, backgrounding, quit Platform Composition and Lifetimes; use AppTerminationTests, MobileAppTests, MobileWorkspaceSessionTests, or MobileForwardingLifecycleTests for the changed lifetime.
Desktop Navigator, sidebar, workspaces, Vault, Assistant layout macOS UI and Workspace Ownership; target window/navigation or layout tests.
Desktop Workspace/Pane sorting, merging, drag-out new windows, or Assistant list reordering TFM Drag and Drop; 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; 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; 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; check platform renderings and ArchitectureBoundaryTests.
SSH/Telnet, credentials, routes, host-key trust, session cleanup SSH, Telnet, Trust, and Workspace Session Lifecycle; 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. For channel admission and backpressure see SSH Multiplexing and I/O Scheduling.
SSH Security Key registration, FIDO2/WebAuthn signing, Vault metadata, or forwarding limits SSH Security Key Authentication; 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, Shell Integration, Port Forwarding Dispatch; choose the matching service or pump tests. For metrics keyboard-auth presentation, use MetricsJourneyRenderingTests on desktop and MobileMetricsJourneyTests on mobile.
SFTP browsing, transfer scheduling, external edit SFTP Transfer, Scheduling, and External Edit Workflow; select the transfer, conflict, or edit suite.
Assistant turns, approvals, host tools, skills, memory Assistant and Agent Runtime; target preparation, cancellation, persistence, tools, or memory tests.
SwiftData, secrets, migrations, CloudKit, settings Persistent Data, Migrations, and Secrets, Settings, Vault, Metrics, History, Device, and Cloud Sync, and CloudKit Release Readiness; select repository, migration, or CloudSyncLifecycleTests / CloudSyncSafetyTests for a sync lifecycle change.
MCP server, external upload/download, bridge MCP Server, Transfers, and Stdio Bridge; run token, server-session, transfer, or bridge tests.
StoreKit, localized copy, widgets, screenshots, website Commerce, Localization, and Product Surfaces, Storefront Commerce Release Checks, Marketing Assets and App Icons, and Build, Test, and Release; use catalog normalization and bilingual validation, app/language, screenshot, StoreKit, or website checks as appropriate.
Picking a deterministic test seam Behavioral Tests and Fixtures; 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 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 and SSH, Telnet, Trust, and Workspace Session Lifecycle.

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 and Build, Test, and Release.

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 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. Keep metadata in persistence and secret values behind Keychain references. Follow Dependency and Ownership Boundaries for imports and Build, Test, and Release for release steps.

For CloudKit changes, follow Settings and Cloud Sync through the release checklist: 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:

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. 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/<Suite>; 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/<Suite>; 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.