commit 47617a25ad1c38c3e05c3fe7d2680f6c0713559f
parent 31105959da51edd4261b13a55bba5ff320a3e414
Author: triesap <tyson@radroots.org>
Date: Wed, 9 Sep 2026 06:44:52 +0000
runtime: close task installation cancellation race
- Cancel operations installed after timeout or cancellation wins.
- Preserve completed results and existing abandoned-result cleanup.
- Extract the actual wrapper and cover all six installation orderings.
- Verify the reproduced regression, full native suite and narrower lint debt.
Diffstat:
8 files changed, 305 insertions(+), 153 deletions(-)
diff --git a/Package.swift b/Package.swift
@@ -58,6 +58,7 @@ let package = Package(
"Runtime/TeraErrorRecovery.swift",
"Runtime/TeraGeneratedRuntimeBackend.swift",
"Runtime/TeraLifecycleCoordinator.swift",
+ "Runtime/TeraRuntimeBoundedTask.swift",
"Runtime/TeraRuntimeClient.swift",
"Runtime/TeraRuntimeModels.swift",
"Runtime/TeraSessionGeneration.swift",
diff --git a/Tera.xcodeproj/project.pbxproj b/Tera.xcodeproj/project.pbxproj
@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
1D45B3D566A0A60063190854 /* TeraApp in Frameworks */ = {isa = PBXBuildFile; productRef = E666175A800272732A27CBEB /* TeraApp */; };
+ 229C9AC991E67663DA53D339 /* TeraRuntimeBoundedTaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A4FFC0023C620B68D0EC0ED /* TeraRuntimeBoundedTaskTests.swift */; };
2479571FA99A7962794999C4 /* TeraSupportingStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0636AEDEB50DDDD328374A9 /* TeraSupportingStoreTests.swift */; };
2C6DDB502DFA11C2CBCA49C4 /* TeraApp in Frameworks */ = {isa = PBXBuildFile; productRef = A1979630FE6BC343F0E59F24 /* TeraApp */; };
38EF7FA8874E82B28110A232 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6967B3EAC4CF1A410B26DD1A /* PrivacyInfo.xcprivacy */; };
@@ -54,6 +55,7 @@
/* Begin PBXFileReference section */
0CDE3D76E1EDF909C19D0506 /* TeraUITests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = TeraUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
27D9D40699A01FFB02F30B11 /* local-social-personas.v1.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "local-social-personas.v1.json"; sourceTree = "<group>"; };
+ 2A4FFC0023C620B68D0EC0ED /* TeraRuntimeBoundedTaskTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraRuntimeBoundedTaskTests.swift; sourceTree = "<group>"; };
2A506546B0EC1792240C36F7 /* TeraClockTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraClockTests.swift; sourceTree = "<group>"; };
32CBDAE974FB8D7408108E69 /* TeraRemoteQualificationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraRemoteQualificationUITests.swift; sourceTree = "<group>"; };
3B808E67E85CD36E49C38B6F /* TeraCalendarFFICompatibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TeraCalendarFFICompatibilityTests.swift; sourceTree = "<group>"; };
@@ -150,6 +152,7 @@
61B6F0B16BFD8F046E9C163F /* TeraMediaStoreTests.swift */,
E351F52E77C74A4E99095E45 /* TeraRemoteQualificationTests.swift */,
6B8677670E203FF68EC88983 /* TeraRootShellTests.swift */,
+ 2A4FFC0023C620B68D0EC0ED /* TeraRuntimeBoundedTaskTests.swift */,
88ED360C84532DA7088BFC6E /* TeraRuntimeClientFixtures.swift */,
FB77C087F15C2F42CD959607 /* TeraRuntimeClientTests.swift */,
7C0836F5D5F71F9A54795C57 /* TeraSessionGenerationTests.swift */,
@@ -372,6 +375,7 @@
CDBE38E6B521611436F28858 /* TeraMediaStoreTests.swift in Sources */,
81AF9DDA0E64DC4EEFCEF25D /* TeraRemoteQualificationTests.swift in Sources */,
9AD968F0B37C64B5AF8D9A68 /* TeraRootShellTests.swift in Sources */,
+ 229C9AC991E67663DA53D339 /* TeraRuntimeBoundedTaskTests.swift in Sources */,
C219B5F4E24188E1116BF45B /* TeraRuntimeClientFixtures.swift in Sources */,
912C8743116D929BB6A02778 /* TeraRuntimeClientTests.swift in Sources */,
79D06C6BF2B55C0C4104FB91 /* TeraSessionGenerationTests.swift in Sources */,
diff --git a/Tera/Runtime/TeraRuntimeBoundedTask.swift b/Tera/Runtime/TeraRuntimeBoundedTask.swift
@@ -0,0 +1,160 @@
+import Foundation
+
+enum TeraRuntimeBoundedOutcome<Value: Sendable>: Sendable {
+ case completed(Result<Value, TeraRuntimeFailure>)
+ case timedOut
+ case cancelled
+}
+
+/// The wrapper has one immutable state owner; every mutable field is protected
+/// by its lock. Task cancellation and continuation resumption occur outside it.
+final class TeraRuntimeBoundedTask<Value: Sendable>: @unchecked Sendable {
+ typealias Outcome = TeraRuntimeBoundedOutcome<Value>
+
+ final class State: @unchecked Sendable {
+ private let lock = NSLock()
+ private var outcome: Outcome?
+ private var continuations: [UUID: CheckedContinuation<Outcome, Never>] = [:]
+ private var cancelledWaiters: Set<UUID> = []
+ private var operationTask: Task<Void, Never>?
+ private var timeoutTask: Task<Void, Never>?
+
+ func install(operationTask: Task<Void, Never>, timeoutTask: Task<Void, Never>) {
+ let terminal = lock.withLock { () -> Outcome? in
+ if let outcome {
+ return outcome
+ }
+ self.operationTask = operationTask
+ self.timeoutTask = timeoutTask
+ return nil
+ }
+ guard let terminal else { return }
+ timeoutTask.cancel()
+ switch terminal {
+ case .cancelled, .timedOut:
+ operationTask.cancel()
+ case .completed:
+ break
+ }
+ }
+
+ func value(cancelsOperationWhenWaiterCancelled: Bool) async -> Outcome {
+ let waiterID = UUID()
+ return await withTaskCancellationHandler {
+ await withCheckedContinuation { requestedContinuation in
+ let immediate = lock.withLock { () -> Outcome? in
+ if let outcome {
+ return outcome
+ }
+ if cancelledWaiters.remove(waiterID) != nil {
+ return .cancelled
+ }
+ continuations[waiterID] = requestedContinuation
+ return nil
+ }
+ if let immediate {
+ requestedContinuation.resume(returning: immediate)
+ }
+ }
+ } onCancel: {
+ if cancelsOperationWhenWaiterCancelled {
+ cancel()
+ } else {
+ cancelWaiter(waiterID)
+ }
+ }
+ }
+
+ func cancel() {
+ guard resolve(.cancelled) else { return }
+ let tasks = lock.withLock { (operationTask, timeoutTask) }
+ tasks.0?.cancel()
+ tasks.1?.cancel()
+ }
+
+ func expire() {
+ guard resolve(.timedOut) else { return }
+ let taskToCancel: Task<Void, Never>? = lock.withLock { self.operationTask }
+ taskToCancel?.cancel()
+ }
+
+ func finishOperation() {
+ lock.withLock { operationTask = nil }
+ }
+
+ private func cancelWaiter(_ waiterID: UUID) {
+ let continuation = lock.withLock { () -> CheckedContinuation<Outcome, Never>? in
+ guard outcome == nil else { return nil }
+ guard let continuation = continuations.removeValue(forKey: waiterID) else {
+ cancelledWaiters.insert(waiterID)
+ return nil
+ }
+ return continuation
+ }
+ continuation?.resume(returning: .cancelled)
+ }
+
+ @discardableResult
+ func resolve(_ requestedOutcome: Outcome) -> Bool {
+ var pendingContinuations: [CheckedContinuation<Outcome, Never>] = []
+ var timeoutToCancel: Task<Void, Never>?
+ let accepted = lock.withLock { () -> Bool in
+ guard outcome == nil else { return false }
+ outcome = requestedOutcome
+ pendingContinuations = Array(continuations.values)
+ continuations.removeAll(keepingCapacity: false)
+ cancelledWaiters.removeAll(keepingCapacity: false)
+ timeoutToCancel = timeoutTask
+ return true
+ }
+ if accepted {
+ timeoutToCancel?.cancel()
+ for continuation in pendingContinuations {
+ continuation.resume(returning: requestedOutcome)
+ }
+ }
+ return accepted
+ }
+ }
+
+ private let state: State
+
+ init(
+ deadlineNanoseconds: UInt64,
+ operation: @escaping @Sendable () async -> Result<Value, TeraRuntimeFailure>,
+ onAbandonedResult:
+ @escaping @Sendable (
+ Result<Value, TeraRuntimeFailure>
+ ) async -> Void = { _ in }
+ ) {
+ let state = State()
+ self.state = state
+ let operationTask = Task { [state] in
+ let result = await operation()
+ if !state.resolve(.completed(result)) {
+ await onAbandonedResult(result)
+ }
+ state.finishOperation()
+ }
+
+ let timeoutTask = Task { [state] in
+ do {
+ try await Task.sleep(nanoseconds: deadlineNanoseconds)
+ } catch {
+ return
+ }
+ state.expire()
+ }
+ state.install(operationTask: operationTask, timeoutTask: timeoutTask)
+ }
+
+ func value(cancelsOperationWhenWaiterCancelled: Bool = true) async -> Outcome {
+ await state.value(
+ cancelsOperationWhenWaiterCancelled: cancelsOperationWhenWaiterCancelled
+ )
+ }
+
+ func cancel() {
+ state.cancel()
+ }
+}
diff --git a/Tera/Runtime/TeraRuntimeClient.swift b/Tera/Runtime/TeraRuntimeClient.swift
@@ -288,156 +288,6 @@ typealias TeraRuntimeBackendFactory =
TeraRuntimeLaunchConfiguration
) async throws -> TeraRuntimeBackendStart
-private enum TeraRuntimeBoundedOutcome<Value: Sendable>: Sendable {
- case completed(Result<Value, TeraRuntimeFailure>)
- case timedOut
- case cancelled
-}
-
-private final class TeraRuntimeBoundedTask<Value: Sendable>: @unchecked Sendable {
- typealias Outcome = TeraRuntimeBoundedOutcome<Value>
-
- private final class State: @unchecked Sendable {
- private let lock = NSLock()
- private var outcome: Outcome?
- private var continuations: [UUID: CheckedContinuation<Outcome, Never>] = [:]
- private var cancelledWaiters: Set<UUID> = []
- private var operationTask: Task<Void, Never>?
- private var timeoutTask: Task<Void, Never>?
-
- func install(operationTask: Task<Void, Never>, timeoutTask: Task<Void, Never>) {
- let shouldCancel = lock.withLock { () -> Bool in
- guard outcome == nil else { return true }
- self.operationTask = operationTask
- self.timeoutTask = timeoutTask
- return false
- }
- if shouldCancel {
- timeoutTask.cancel()
- }
- }
-
- func value(cancelsOperationWhenWaiterCancelled: Bool) async -> Outcome {
- let waiterID = UUID()
- return await withTaskCancellationHandler {
- await withCheckedContinuation { requestedContinuation in
- let immediate = lock.withLock { () -> Outcome? in
- if let outcome {
- return outcome
- }
- if cancelledWaiters.remove(waiterID) != nil {
- return .cancelled
- }
- continuations[waiterID] = requestedContinuation
- return nil
- }
- if let immediate {
- requestedContinuation.resume(returning: immediate)
- }
- }
- } onCancel: {
- if cancelsOperationWhenWaiterCancelled {
- cancel()
- } else {
- cancelWaiter(waiterID)
- }
- }
- }
-
- func cancel() {
- guard resolve(.cancelled) else { return }
- let tasks = lock.withLock { (operationTask, timeoutTask) }
- tasks.0?.cancel()
- tasks.1?.cancel()
- }
-
- func expire() {
- guard resolve(.timedOut) else { return }
- let taskToCancel: Task<Void, Never>? = lock.withLock { self.operationTask }
- taskToCancel?.cancel()
- }
-
- func finishOperation() {
- lock.withLock { operationTask = nil }
- }
-
- private func cancelWaiter(_ waiterID: UUID) {
- let continuation = lock.withLock { () -> CheckedContinuation<Outcome, Never>? in
- guard outcome == nil else { return nil }
- guard let continuation = continuations.removeValue(forKey: waiterID) else {
- cancelledWaiters.insert(waiterID)
- return nil
- }
- return continuation
- }
- continuation?.resume(returning: .cancelled)
- }
-
- @discardableResult
- func resolve(_ requestedOutcome: Outcome) -> Bool {
- var pendingContinuations: [CheckedContinuation<Outcome, Never>] = []
- var timeoutToCancel: Task<Void, Never>?
- let accepted = lock.withLock { () -> Bool in
- guard outcome == nil else { return false }
- outcome = requestedOutcome
- pendingContinuations = Array(continuations.values)
- continuations.removeAll(keepingCapacity: false)
- cancelledWaiters.removeAll(keepingCapacity: false)
- timeoutToCancel = timeoutTask
- return true
- }
- if accepted {
- timeoutToCancel?.cancel()
- for continuation in pendingContinuations {
- continuation.resume(returning: requestedOutcome)
- }
- }
- return accepted
- }
- }
-
- private let state: State
-
- init(
- deadlineNanoseconds: UInt64,
- operation: @escaping @Sendable () async -> Result<Value, TeraRuntimeFailure>,
- onAbandonedResult:
- @escaping @Sendable (
- Result<Value, TeraRuntimeFailure>
- ) async -> Void = { _ in }
- ) {
- let state = State()
- self.state = state
- let operationTask = Task { [state] in
- let result = await operation()
- if !state.resolve(.completed(result)) {
- await onAbandonedResult(result)
- }
- state.finishOperation()
- }
-
- let timeoutTask = Task { [state] in
- do {
- try await Task.sleep(nanoseconds: deadlineNanoseconds)
- } catch {
- return
- }
- state.expire()
- }
- state.install(operationTask: operationTask, timeoutTask: timeoutTask)
- }
-
- func value(cancelsOperationWhenWaiterCancelled: Bool = true) async -> Outcome {
- await state.value(
- cancelsOperationWhenWaiterCancelled: cancelsOperationWhenWaiterCancelled
- )
- }
-
- func cancel() {
- state.cancel()
- }
-}
-
actor TeraRuntimeClient {
private struct StartupOperation: Sendable {
let identity: TeraRuntimeOperationIdentity
diff --git a/TeraTests/TeraRuntimeBoundedTaskTests.swift b/TeraTests/TeraRuntimeBoundedTaskTests.swift
@@ -0,0 +1,136 @@
+import Foundation
+@testable import TeraApp
+import XCTest
+
+final class TeraRuntimeBoundedTaskTests: XCTestCase {
+ private typealias Bounded = TeraRuntimeBoundedTask<Int>
+
+ func testCompletionTimeoutAndCancellationBeforeInstallation() async {
+ for terminal in Terminal.allCases {
+ await assertInstallation(terminal: terminal, terminalFirst: true)
+ }
+ }
+
+ func testCompletionTimeoutAndCancellationAfterInstallation() async {
+ for terminal in Terminal.allCases {
+ await assertInstallation(terminal: terminal, terminalFirst: false)
+ }
+ }
+
+ func testCompletedFailureDoesNotCancelLateInstalledOperation() async {
+ let state = Bounded.State()
+ let gate = BoundedTestGate()
+ let operation = Task { await gate.wait() }
+ let timer = Task { await gate.wait() }
+ let failure = TeraRuntimeFailure.local(operation: "test", code: "test.failure", safeMessage: "Test failure")
+ XCTAssertTrue(state.resolve(.completed(.failure(failure))))
+ state.install(operationTask: operation, timeoutTask: timer)
+ XCTAssertFalse(operation.isCancelled)
+ XCTAssertTrue(timer.isCancelled)
+ if case let .completed(.failure(observed)) = await state.value(cancelsOperationWhenWaiterCancelled: true) {
+ XCTAssertEqual(observed, failure)
+ } else {
+ XCTFail("The first completed result must remain owned by its caller")
+ }
+ await gate.open()
+ await operation.value
+ await timer.value
+ }
+
+ func testAbandonedSuccessfulOperationStillRunsItsCleanupExactlyOnce() async {
+ let started = BoundedTestGate()
+ let release = BoundedTestGate()
+ let abandoned = expectation(description: "Abandoned result cleanup")
+ abandoned.assertForOverFulfill = true
+ let task = Bounded(deadlineNanoseconds: .max) {
+ await started.open()
+ await release.wait()
+ return .success(42)
+ } onAbandonedResult: { result in
+ XCTAssertEqual(try? result.get(), 42)
+ abandoned.fulfill()
+ }
+ await started.wait()
+ task.cancel()
+ task.cancel()
+ if case .cancelled = await task.value() {} else {
+ XCTFail("Cancellation must resolve the caller before the operation returns")
+ }
+ await release.open()
+ await fulfillment(of: [abandoned], timeout: 2)
+ }
+
+ func testSuccessfulWrapperKeepsItsResultAfterLaterCancellation() async {
+ let task = Bounded(deadlineNanoseconds: .max, operation: { .success(42) }) { _ in
+ XCTFail("A result owned by its caller must not be abandoned")
+ }
+ await assertOutcome(task.value(), terminal: .completion)
+ task.cancel()
+ await assertOutcome(task.value(), terminal: .completion)
+ }
+
+ private func assertInstallation(terminal: Terminal, terminalFirst: Bool) async {
+ let state = Bounded.State()
+ let gate = BoundedTestGate()
+ let operation = Task { await gate.wait() }
+ let timer = Task { await gate.wait() }
+ if terminalFirst {
+ terminal.resolve(state)
+ }
+ state.install(operationTask: operation, timeoutTask: timer)
+ if !terminalFirst {
+ terminal.resolve(state)
+ }
+ XCTAssertEqual(operation.isCancelled, terminal != .completion, "\(terminal), before=\(terminalFirst)")
+ XCTAssertTrue(timer.isCancelled)
+ await assertOutcome(state.value(cancelsOperationWhenWaiterCancelled: true), terminal: terminal)
+ XCTAssertFalse(state.resolve(.completed(.success(99))))
+ state.cancel()
+ state.expire()
+ await assertOutcome(state.value(cancelsOperationWhenWaiterCancelled: true), terminal: terminal)
+ await gate.open()
+ await operation.value
+ await timer.value
+ state.finishOperation()
+ }
+
+ private func assertOutcome(_ outcome: Bounded.Outcome, terminal: Terminal) {
+ switch (terminal, outcome) {
+ case let (.completion, .completed(.success(value))): XCTAssertEqual(value, 42)
+ case (.timeout, .timedOut), (.cancellation, .cancelled): break
+ default: XCTFail("The first terminal outcome must resolve each wait exactly once")
+ }
+ }
+
+ private enum Terminal: CaseIterable {
+ case completion, timeout, cancellation
+
+ func resolve(_ state: Bounded.State) {
+ switch self {
+ case .completion: XCTAssertTrue(state.resolve(.completed(.success(42))))
+ case .timeout: state.expire()
+ case .cancellation: state.cancel()
+ }
+ }
+ }
+}
+
+private actor BoundedTestGate {
+ private var opened = false
+ private var waiters: [CheckedContinuation<Void, Never>] = []
+
+ func wait() async {
+ guard !opened else { return }
+ await withCheckedContinuation { waiters.append($0) }
+ }
+
+ func open() {
+ guard !opened else { return }
+ opened = true
+ let pending = waiters
+ waiters.removeAll()
+ for waiter in pending {
+ waiter.resume()
+ }
+ }
+}
diff --git a/project.yml b/project.yml
@@ -49,6 +49,7 @@ targets:
- path: TeraTests/TeraRuntimeClientFixtures.swift
- path: TeraTests/TeraSessionGenerationTests.swift
- path: TeraTests/TeraErrorRecoveryTests.swift
+ - path: TeraTests/TeraRuntimeBoundedTaskTests.swift
- path: TeraTests/TeraRootShellTests.swift
- path: TeraTests/TeraStateMigrationTests.swift
- path: TeraTests/TeraTodayStoreTests.swift
diff --git a/release/provenance.json b/release/provenance.json
@@ -6,7 +6,7 @@
"info_plist_sha256": "15ef08b1cdd1096cfb9eeaf5be5bf8f814807a7ca9350bbbb47860fa72ec13ef",
"privacy_manifest_sha256": "a331d51864743ebe4e00dd22360b4a538b6b3ac26a6b3eb54094e60a36959a12",
"sbom_sha256": "6b5ce897d5273290febc8b831663e12dea759cb0084f182ba7949e1c593fc410",
- "xcode_project_sha256": "6ff877e0e0a57a08b15c9fa9857e952fd1f1bb566fe3b79b9a4078b8dcb6c80d"
+ "xcode_project_sha256": "4d8248344c4728688df5b51fc9127b08a50aab252b177956ea76a8ab31ecfb31"
},
"disposition": "unsigned",
"platforms": [
diff --git a/test-fixtures/swiftlint-maintainability-baseline.v1.json b/test-fixtures/swiftlint-maintainability-baseline.v1.json
@@ -1 +1 @@
-[{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/App\/TeraAppModel.swift","character":7,"line":55},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 255 lines"},"text":"final class TeraAppModel: ObservableObject {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/App\/TeraAppModel.swift","character":3,"line":71},"severity":"warning","reason":"Initializer body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines"},"text":" init("},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","character":1,"line":73},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 427 lines"},"text":"actor TeraAddMediaCoordinator: TeraAddMediaHandling {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","character":3,"line":192},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 55 lines"},"text":" func uploadInBackground("},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","character":1,"line":580},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 580"},"text":"#endif"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","character":15,"line":134},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 545 lines"},"text":"private final class TeraGeneratedRuntimeBackend: TeraRuntimeBackend, @unchecked Sendable {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","character":1,"line":1696},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1696"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraLifecycleCoordinator.swift","character":1,"line":434},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 434"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":1,"line":441},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 847 lines"},"text":"actor TeraRuntimeClient {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":11,"line":503},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines"},"text":" private func start("},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":3,"line":881},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 88 lines"},"text":" func changes(bufferCapacity: Int = 16) async throws -> AsyncStream<TeraRuntimeChange> {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":11,"line":1061},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines"},"text":" private func beginShutdown() -> ShutdownOperation {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","character":1,"line":1371},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1371"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Runtime\/TeraRuntimeModels.swift","character":1,"line":1234},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1234"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":7,"line":11},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 741 lines"},"text":"final class TeraAddStore: ObservableObject {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":3,"line":280},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines"},"text":" func submit() async {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":3,"line":438},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 51 lines"},"text":" func retract(_ card: TeraTodayCard) async {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraAddStore.swift","character":11,"line":524},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines"},"text":" private func uploadPendingMedia(_ initial: TeraDraftStatus) async throws"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraAddStore.swift","character":1,"line":810},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 810"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","character":1,"line":78},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 468 lines"},"text":"actor TeraConfigurationStore {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","character":5,"line":148},"severity":"error","reason":"Function body should span 100 lines or less excluding comments and whitespace: currently spans 109 lines"},"text":" func load() throws -> TeraAppConfiguration {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","character":1,"line":759},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 759"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":1,"line":40},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 431 lines"},"text":"actor TeraSessionStore {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":10,"line":70},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines"},"text":" static func production("},{"violation":{"ruleName":"Cyclomatic Complexity","ruleIdentifier":"cyclomatic_complexity","ruleDescription":"Complexity of function bodies should be limited.","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":11,"line":182},"severity":"warning","reason":"Function should have complexity 10 or less; currently complexity is 14"},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":11,"line":182},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 64 lines"},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":11,"line":389},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines"},"text":" private func reconcileIdentity(_ identity: TeraAppIdentity) async throws {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraSessionStore.swift","character":1,"line":493},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 493"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/State\/TeraSupportingStores.swift","character":1,"line":451},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 451"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/State\/TeraTodayStore.swift","character":7,"line":13},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 257 lines"},"text":"final class TeraTodayStore: ObservableObject {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Views\/TeraAddView.swift","character":1,"line":4},"severity":"error","reason":"Struct body should span 350 lines or less excluding comments and whitespace: currently spans 454 lines"},"text":"struct TeraAddView: View {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Views\/TeraAddView.swift","character":1,"line":560},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 560"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","character":1,"line":365},"severity":"warning","reason":"Struct body should span 250 lines or less excluding comments and whitespace: currently spans 259 lines"},"text":"struct TeraSettingsView: View {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","character":1,"line":629},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 629"},"text":"}"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"Tera\/Views\/TeraTodayView.swift","character":1,"line":493},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 493"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":7,"line":6},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 665 lines"},"text":"final class TeraAddStoreTests: XCTestCase {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":9,"line":847},"severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 579 lines"},"text":"private actor AddBackend: TeraRuntimeBackend {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":22,"line":934},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 89 lines"},"text":" nonisolated static func schemas() -> [TeraAddSchema] {"},{"violation":{"ruleName":"Function Parameter Count","ruleIdentifier":"function_parameter_count","ruleDescription":"Number of function parameters should be low.","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":11,"line":1371},"severity":"warning","reason":"Function should have 5 parameters or less: it currently has 8"},"text":" private func makeStatus("},{"violation":{"ruleName":"Large Tuple","ruleIdentifier":"large_tuple","ruleDescription":"Tuples shouldn't have too many members. Create a custom type instead.","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":15,"line":1635},"severity":"error","reason":"Tuples should have at most 2 members"},"text":" var counts: (enqueue: Int, retry: Int, cancel: Int, acceptedSettlement: Int) {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraTests\/TeraAddStoreTests.swift","character":1,"line":1784},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 1784"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","character":7,"line":7},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 307 lines"},"text":"final class TeraRemoteQualificationTests: XCTestCase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","character":3,"line":45},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 94 lines"},"text":" func testQualificationRejectsAmbiguousOrUnsafeHarnessValues() {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","character":3,"line":212},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines"},"text":" func testAuthorizationEvidenceIsRedactedEphemeralAndRelaunchCleaned() throws {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraRuntimeClientTests.swift","character":7,"line":4},"severity":"warning","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 334 lines"},"text":"final class TeraRuntimeClientTests: XCTestCase {"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","character":7,"line":6},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 580 lines"},"text":"final class TeraStateMigrationTests: XCTestCase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","character":5,"line":7},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines"},"text":" func testRelayValidationMatchesRuntimeProfiles() throws {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","character":1,"line":718},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 718"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","character":9,"line":207},"severity":"warning","reason":"Actor body should span 250 lines or less excluding comments and whitespace: currently spans 253 lines"},"text":"private actor SupportingBackend: TeraRuntimeBackend {"},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","character":1,"line":487},"severity":"warning","reason":"File should contain 400 lines or less: currently contains 487"},"text":"}"},{"violation":{"ruleName":"Type Body Length","ruleIdentifier":"type_body_length","ruleDescription":"Type bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":7,"line":4},"severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 1493 lines"},"text":"final class TeraRemoteQualificationUITests: XCTestCase {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":3,"line":62},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 73 lines"},"text":" func testLocalSocialFiveFlowScenario() throws {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":3,"line":174},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines"},"text":" func testLocalSocialDeterministicPersonas() throws {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":3,"line":247},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 54 lines"},"text":" func testRemoteBlossomUploadAndRecovery() throws {"},{"violation":{"ruleName":"Cyclomatic Complexity","ruleIdentifier":"cyclomatic_complexity","ruleDescription":"Complexity of function bodies should be limited.","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":11,"line":573},"severity":"warning","reason":"Function should have complexity 10 or less; currently complexity is 18"},"text":" private func expectedAddFieldLabel(_ identifier: String, type: String) -> String {"},{"violation":{"ruleName":"Cyclomatic Complexity","ruleIdentifier":"cyclomatic_complexity","ruleDescription":"Complexity of function bodies should be limited.","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":11,"line":767},"severity":"warning","reason":"Function should have complexity 10 or less; currently complexity is 11"},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":11,"line":767},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines"},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleName":"Function Body Length","ruleIdentifier":"function_body_length","ruleDescription":"Function bodies should not span too many lines","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":10,"line":1736},"severity":"warning","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 67 lines"},"text":" static func environment("},{"violation":{"ruleName":"File Length","ruleIdentifier":"file_length","ruleDescription":"Files should not span too many lines.","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","character":1,"line":2212},"severity":"error","reason":"File should contain 1000 lines or less: currently contains 2212"},"text":"}"}]
-\ No newline at end of file
+[{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/App\/TeraAppModel.swift","line":55,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 255 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraAppModel: ObservableObject {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/App\/TeraAppModel.swift","line":71,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Initializer body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" init("},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","line":73,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 427 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraAddMediaCoordinator: TeraAddMediaHandling {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","line":192,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 55 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func uploadInBackground("},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraAddMediaCoordinator.swift","line":580,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 580","ruleDescription":"Files should not span too many lines."},"text":"#endif"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","line":134,"character":15},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 545 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"private final class TeraGeneratedRuntimeBackend: TeraRuntimeBackend, @unchecked Sendable {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraGeneratedRuntimeBackend.swift","line":1696,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1696","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraLifecycleCoordinator.swift","line":434,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 434","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":291,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 847 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraRuntimeClient {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":353,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func start("},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":731,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 88 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func changes(bufferCapacity: Int = 16) async throws -> AsyncStream<TeraRuntimeChange> {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":911,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func beginShutdown() -> ShutdownOperation {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraRuntimeClient.swift","line":1221,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1221","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Runtime\/TeraRuntimeModels.swift","line":1234,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1234","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":11,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 741 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraAddStore: ObservableObject {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":280,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func submit() async {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":438,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 51 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func retract(_ card: TeraTodayCard) async {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":524,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 60 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func uploadPendingMedia(_ initial: TeraDraftStatus) async throws"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraAddStore.swift","line":810,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 810","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","line":78,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 468 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraConfigurationStore {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","line":148,"character":5},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 100 lines or less excluding comments and whitespace: currently spans 109 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func load() throws -> TeraAppConfiguration {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraConfigurationStore.swift","line":759,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 759","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":40,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 431 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"actor TeraSessionStore {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":70,"character":10},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 52 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" static func production("},{"violation":{"ruleIdentifier":"cyclomatic_complexity","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":182,"character":11},"ruleName":"Cyclomatic Complexity","severity":"error","reason":"Function should have complexity 10 or less; currently complexity is 14","ruleDescription":"Complexity of function bodies should be limited."},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":182,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 64 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func start(acceptingReconfiguration: Bool) async -> TeraSessionPhase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":389,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func reconcileIdentity(_ identity: TeraAppIdentity) async throws {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraSessionStore.swift","line":493,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 493","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/State\/TeraSupportingStores.swift","line":451,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 451","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Views\/TeraAddView.swift","line":4,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Struct body should span 350 lines or less excluding comments and whitespace: currently spans 454 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"struct TeraAddView: View {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Views\/TeraAddView.swift","line":560,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 560","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","line":365,"character":1},"ruleName":"Type Body Length","severity":"error","reason":"Struct body should span 250 lines or less excluding comments and whitespace: currently spans 259 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"struct TeraSettingsView: View {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Views\/TeraSupportingViews.swift","line":629,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 629","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"Tera\/Views\/TeraTodayView.swift","line":493,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 493","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":6,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 665 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraAddStoreTests: XCTestCase {"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":847,"character":9},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 350 lines or less excluding comments and whitespace: currently spans 579 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"private actor AddBackend: TeraRuntimeBackend {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":934,"character":22},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 89 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" nonisolated static func schemas() -> [TeraAddSchema] {"},{"violation":{"ruleIdentifier":"function_parameter_count","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":1371,"character":11},"ruleName":"Function Parameter Count","severity":"error","reason":"Function should have 5 parameters or less: it currently has 8","ruleDescription":"Number of function parameters should be low."},"text":" private func makeStatus("},{"violation":{"ruleIdentifier":"large_tuple","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":1635,"character":15},"ruleName":"Large Tuple","severity":"error","reason":"Tuples should have at most 2 members","ruleDescription":"Tuples shouldn't have too many members. Create a custom type instead."},"text":" var counts: (enqueue: Int, retry: Int, cancel: Int, acceptedSettlement: Int) {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraTests\/TeraAddStoreTests.swift","line":1784,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 1784","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","line":7,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 307 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraRemoteQualificationTests: XCTestCase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","line":45,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 94 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testQualificationRejectsAmbiguousOrUnsafeHarnessValues() {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraRemoteQualificationTests.swift","line":212,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 53 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testAuthorizationEvidenceIsRedactedEphemeralAndRelaunchCleaned() throws {"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraRuntimeClientTests.swift","line":4,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 250 lines or less excluding comments and whitespace: currently spans 334 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraRuntimeClientTests: XCTestCase {"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","line":6,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 580 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraStateMigrationTests: XCTestCase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","line":7,"character":5},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 61 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testRelayValidationMatchesRuntimeProfiles() throws {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraTests\/TeraStateMigrationTests.swift","line":718,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 718","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","line":207,"character":9},"ruleName":"Type Body Length","severity":"error","reason":"Actor body should span 250 lines or less excluding comments and whitespace: currently spans 253 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"private actor SupportingBackend: TeraRuntimeBackend {"},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraTests\/TeraSupportingStoreTests.swift","line":487,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 400 lines or less: currently contains 487","ruleDescription":"Files should not span too many lines."},"text":"}"},{"violation":{"ruleIdentifier":"type_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":4,"character":7},"ruleName":"Type Body Length","severity":"error","reason":"Class body should span 350 lines or less excluding comments and whitespace: currently spans 1493 lines","ruleDescription":"Type bodies should not span too many lines"},"text":"final class TeraRemoteQualificationUITests: XCTestCase {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":62,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 73 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testLocalSocialFiveFlowScenario() throws {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":174,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testLocalSocialDeterministicPersonas() throws {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":247,"character":3},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 54 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" func testRemoteBlossomUploadAndRecovery() throws {"},{"violation":{"ruleIdentifier":"cyclomatic_complexity","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":573,"character":11},"ruleName":"Cyclomatic Complexity","severity":"error","reason":"Function should have complexity 10 or less; currently complexity is 18","ruleDescription":"Complexity of function bodies should be limited."},"text":" private func expectedAddFieldLabel(_ identifier: String, type: String) -> String {"},{"violation":{"ruleIdentifier":"cyclomatic_complexity","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":767,"character":11},"ruleName":"Cyclomatic Complexity","severity":"error","reason":"Function should have complexity 10 or less; currently complexity is 11","ruleDescription":"Complexity of function bodies should be limited."},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":767,"character":11},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 66 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" private func preparePhotoUpdate(_ app: XCUIApplication, marker: String) -> XCUIElement? {"},{"violation":{"ruleIdentifier":"function_body_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":1736,"character":10},"ruleName":"Function Body Length","severity":"error","reason":"Function body should span 50 lines or less excluding comments and whitespace: currently spans 67 lines","ruleDescription":"Function bodies should not span too many lines"},"text":" static func environment("},{"violation":{"ruleIdentifier":"file_length","location":{"file":"TeraUITests\/TeraRemoteQualificationUITests.swift","line":2212,"character":1},"ruleName":"File Length","severity":"error","reason":"File should contain 1000 lines or less: currently contains 2212","ruleDescription":"Files should not span too many lines."},"text":"}"}]
+\ No newline at end of file