Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b18dfac
Add syntax highlighting to the built-in file preview
Jun 26, 2026
1745951
Merge remote-tracking branch 'origin/main' into issue-6773-feature-re…
Jun 26, 2026
3e817a5
Fix file preview syntax highlighting: cmux.json parser, compile error…
Jun 26, 2026
76a130c
Refresh Swift file-length budget for syntax-highlighting parser + tes…
Jun 26, 2026
8cf158b
Split syntax highlighter into one-type-per-file; justify debounce
Jun 26, 2026
ada3a11
Update MarkdownPanelView's FilePreviewTextEditor call for new params
Jun 26, 2026
488d702
Merge remote-tracking branch 'origin/main' into issue-6773-feature-re…
austinywang Jul 3, 2026
e8df30f
Fix CSS syntax comment detection
austinywang Jul 3, 2026
375a721
Cancel file preview syntax highlight tasks
austinywang Jul 3, 2026
97cf807
Avoid unnecessary syntax highlight clears
austinywang Jul 3, 2026
b3b8d02
Cap file preview syntax token application
austinywang Jul 3, 2026
d5733ce
Merge remote-tracking branch 'origin/main' into issue-6773-feature-re…
austinywang Jul 4, 2026
3f6e57c
Address syntax highlight review policy
austinywang Jul 4, 2026
2f7354c
Fix Rust lifetime highlighting
austinywang Jul 4, 2026
555aed9
Merge remote-tracking branch 'origin/main' into issue-6773-feature-re…
austinywang Aug 14, 2026
c04c91d
feat(file-preview): finish syntax highlighting
austinywang Aug 14, 2026
51641f2
fix(file-preview): address highlighting review
austinywang Aug 14, 2026
bded351
test(settings): isolate syntax highlighting defaults
austinywang Aug 14, 2026
676ce18
fix(ios-tests): avoid Swift Testing closure sendability macro
austinywang Aug 14, 2026
bc1956c
fix(ios-tests): restore diagnostic presentation semantics
austinywang Aug 14, 2026
9d4941d
Merge remote-tracking branch 'origin/main' into issue-6773-feature-re…
austinywang Aug 14, 2026
b2bc55e
test(ios): keep session IDs out of summaries
austinywang Aug 14, 2026
703abb2
fix(ios): redact session IDs from summaries
austinywang Aug 14, 2026
363adff
fix(ios): scope workspace group helpers
austinywang Aug 14, 2026
f7eabf1
fix(ios-tests): pass scroll interaction generation
austinywang Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,7 @@ jobs:
CmuxIrohTransport
CmuxCommandPalette
CmuxControlSocket
CmuxFilePreviewSyntax
CmuxFoundation
CmuxGit
CmuxNotifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Foundation
/// The git SHA and dev tag are signed bundle metadata, not runtime input. The
/// helper keeps iOS and macOS reports comparable and applies the same bounded
/// sanitization at their shared boundary.
// `DiagnosticBuildStamp.make` is a stable API shared by the Mac and iOS shells.
// lint:allow namespace-enum, namespace-type — stable stateless formatter API
public enum DiagnosticBuildStamp {
/// Returns a bounded `name version (build) tag sha` stamp from bundle data.
public static func make(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -487,17 +487,17 @@ public struct DiagnosticEventPresentation: Sendable {
case .appFeatureAction:
localized("diagnostics.event.appFeatureAction", defaultValue: "App feature event")
case .transportDialPlanBuilt:
localized("diagnostics.event.transportDialPlanBuilt", defaultValue: "Direct dial plan assembled")
localized("diagnostics.event.transportDialPlanBuilt", defaultValue: "Transport dial plan built")
case .transportPrivateAddressJoin:
localized("diagnostics.event.transportPrivateAddressJoin", defaultValue: "Private addresses joined broker port")
localized("diagnostics.event.transportPrivateAddressJoin", defaultValue: "Private address candidate joined")
case .transportLANDiscovery:
localized("diagnostics.event.transportLANDiscovery", defaultValue: "LAN discovery resolved")
localized("diagnostics.event.transportLANDiscovery", defaultValue: "LAN discovery completed")
case .transportDialLegSucceeded:
localized("diagnostics.event.transportDialLegSucceeded", defaultValue: "Direct dial leg connected")
localized("diagnostics.event.transportDialLegSucceeded", defaultValue: "Direct dial leg succeeded")
case .transportDialLegFailed:
localized("diagnostics.event.transportDialLegFailed", defaultValue: "Direct dial leg failed")
case .lanPublicationState:
localized("diagnostics.event.lanPublicationState", defaultValue: "LAN advertisement state changed")
localized("diagnostics.event.lanPublicationState", defaultValue: "LAN publication state changed")
}
}

Expand Down Expand Up @@ -540,6 +540,12 @@ public struct DiagnosticEventPresentation: Sendable {
return Field(key: "editable_focused", value: booleanName(raw))
case .browserPanelCreateResolved:
return Field(key: "created", value: booleanName(raw))
case .transportDialSessionLinked:
return Field(key: "attempt", value: String(raw))
case .transportDialCancelled:
return Field(key: "cancellation", value: cancellationReasonName(raw))
case .transportCloseReason:
return Field(key: "reason", value: remoteCloseReasonName(raw))
case .simulatorStreamLifecycle:
return Field(key: "state", value: simulatorStreamLifecycleName(raw))
case .simulatorFrameLifecycle:
Expand Down Expand Up @@ -592,6 +598,8 @@ public struct DiagnosticEventPresentation: Sendable {
return Field(key: "outcome", value: browserFocusOutcomeName(raw))
case .transportDialPlanBuilt:
return Field(key: "private_fallback_paths", value: String(raw))
case .transportDialCancelled:
return Field(key: "detail_2", value: String(raw))
case .discoverySucceeded:
return Field(key: "bindings", value: String(raw))
case .transportPrivateAddressJoin:
Expand Down Expand Up @@ -643,6 +651,14 @@ public struct DiagnosticEventPresentation: Sendable {
return Field(key: "relay_fleet", value: String(raw))
case .transportDialStarted, .transportDialConnected, .transportDialFailed:
return Field(key: "attempt", value: String(raw))
case .transportDialSessionLinked:
return Field(key: "session", value: String(raw))
case .transportDialCancelled:
return Field(key: "attempt", value: String(raw))
case .transportCloseReason:
return Field(key: "session", value: String(raw))
case .recoveryStarted, .recoverySucceeded, .recoveryFailed:
return Field(key: "peer", value: String(raw))
case .sessionClosed, .transportSessionLifecycle,
.transportCloseAttribution, .transportPathEvent:
return Field(key: "session", value: String(raw))
Expand Down Expand Up @@ -703,6 +719,56 @@ public struct DiagnosticEventPresentation: Sendable {
return name(kind)
}

private func cancellationReasonName(_ raw: Int) -> String {
guard let value = DiagnosticCancellationReason(rawValue: raw) else {
return localized(
"diagnostics.unknown.cancellation",
defaultValue: "Unknown cancellation (\(raw))"
)
}
switch value {
case .unknown:
return localized("diagnostics.cancellation.unknown", defaultValue: "Unknown cancellation")
case .requestCancelled:
return localized("diagnostics.cancellation.requestCancelled", defaultValue: "Request cancelled")
case .requestTimedOut:
return localized("diagnostics.cancellation.requestTimedOut", defaultValue: "Request timed out")
case .sessionTeardown:
return localized("diagnostics.cancellation.sessionTeardown", defaultValue: "Session torn down")
case .sessionDeinitialized:
return localized("diagnostics.cancellation.sessionDeinitialized", defaultValue: "Session deinitialized")
}
}

private func remoteCloseReasonName(_ raw: Int) -> String {
guard let value = DiagnosticRemoteCloseReason(rawValue: raw) else {
return localized(
"diagnostics.unknown.closeReason",
defaultValue: "Unknown remote reason (\(raw))"
)
}
switch value {
case .unknown:
return localized("diagnostics.closeReason.unknown", defaultValue: "Unknown remote reason")
case .clientClosed:
return localized("diagnostics.closeReason.clientClosed", defaultValue: "Client closed")
case .serverClosed:
return localized("diagnostics.closeReason.serverClosed", defaultValue: "Server closed")
case .superseded:
return localized("diagnostics.closeReason.superseded", defaultValue: "Superseded session")
case .admissionLeaseExpired:
return localized("diagnostics.closeReason.admissionLeaseExpired", defaultValue: "Admission lease expired")
case .admissionRevalidationFailed:
return localized("diagnostics.closeReason.admissionRevalidationFailed", defaultValue: "Admission revalidation failed")
case .sendQueueOverflow:
return localized("diagnostics.closeReason.sendQueueOverflow", defaultValue: "Send queue overflow")
case .serverFailure:
return localized("diagnostics.closeReason.serverFailure", defaultValue: "Server failure")
case .serverCancelled:
return localized("diagnostics.closeReason.serverCancelled", defaultValue: "Server cancelled")
}
}

private func terminalToolbarActionName(_ raw: Int) -> String {
DiagnosticTerminalToolbarAction(rawValue: raw).map(name)
?? unknownPayloadName(raw)
Expand Down Expand Up @@ -1349,6 +1415,8 @@ public struct DiagnosticEventPresentation: Sendable {
private func label(for key: String) -> String {
switch key {
case "surface": localized("diagnostics.field.surface", defaultValue: "Surface")
case "peer": localized("diagnostics.field.peer", defaultValue: "Peer")
case "recovery": localized("diagnostics.field.recovery", defaultValue: "Recovery")
case "transport": localized("diagnostics.field.transport", defaultValue: "Transport")
case "failure": localized("diagnostics.field.failure", defaultValue: "Failure")
case "attempt": localized("diagnostics.field.attempt", defaultValue: "Attempt")
Expand Down Expand Up @@ -1395,6 +1463,7 @@ public struct DiagnosticEventPresentation: Sendable {
case "route": localized("diagnostics.field.route", defaultValue: "Route")
case "style": localized("diagnostics.field.style", defaultValue: "Style")
case "reason": localized("diagnostics.field.reason", defaultValue: "Reason")
case "cancellation": localized("diagnostics.field.cancellation", defaultValue: "Cancellation")
case "outcome": localized("diagnostics.field.outcome", defaultValue: "Outcome")
case "editable_focused": localized("diagnostics.field.editableFocused", defaultValue: "Editable focused")
case "created": localized("diagnostics.field.created", defaultValue: "Created")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -690,13 +690,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "LAN advertisement state changed"
"value": "LAN publication state changed"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "LANアドバタイズ状態が変化しました"
"value": "LAN公開状態が変化しました"
}
}
}
Expand Down Expand Up @@ -1098,13 +1098,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Direct dial leg connected"
"value": "Direct dial leg succeeded"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "直接ダイヤル経路が接続しました"
"value": "直接ダイヤル経路が成功しました"
}
}
}
Expand All @@ -1115,13 +1115,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Direct dial plan assembled"
"value": "Transport dial plan built"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "直接ダイヤルプランを作成しました"
"value": "トランスポートのダイヤルプランを作成しました"
}
}
}
Expand Down Expand Up @@ -1149,7 +1149,7 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "LAN discovery resolved"
"value": "LAN discovery completed"
}
},
"ja": {
Expand Down Expand Up @@ -1183,13 +1183,13 @@
"en": {
"stringUnit": {
"state": "translated",
"value": "Private addresses joined broker port"
"value": "Private address candidate joined"
}
},
"ja": {
"stringUnit": {
"state": "translated",
"value": "プライベートアドレスをブローカーのポートと結合しました"
"value": "プライベートアドレス候補が追加されました"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,11 @@ import Testing
.init(key: "session", value: "9"),
])
let closeSummary = englishPresentation.summary(close)
#expect(closeSummary.contains("Session"))
#expect(closeSummary.contains("9"))
#expect(closeSummary.contains("Initiator: Timed out"))
#expect(closeSummary.contains("Failure: Transport idle timed out"))
#expect(closeSummary.contains("Application error code: 7"))
#expect(!closeSummary.contains("Session"))
#expect(!closeSummary.contains("9"))
}

@Test func describesLifecycleAndReachability() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1014,45 +1014,47 @@ struct TaskComposerSheet: View {

}

private func validWorkspaceGroupID(
_ candidate: MobileWorkspaceGroupPreview.ID?,
groups: [MobileWorkspaceGroupPreview],
macDeviceID: String,
instanceTag: String?
) -> MobileWorkspaceGroupPreview.ID? {
guard let candidate,
filteredWorkspaceGroups(
groups,
macDeviceID: macDeviceID,
instanceTag: instanceTag
).contains(where: { $0.id == candidate }) else {
return nil
private extension TaskComposerSheet {
func validWorkspaceGroupID(
_ candidate: MobileWorkspaceGroupPreview.ID?,
groups: [MobileWorkspaceGroupPreview],
macDeviceID: String,
instanceTag: String?
) -> MobileWorkspaceGroupPreview.ID? {
guard let candidate,
filteredWorkspaceGroups(
groups,
macDeviceID: macDeviceID,
instanceTag: instanceTag
).contains(where: { $0.id == candidate }) else {
return nil
}
return candidate
}
return candidate
}

private func filteredWorkspaceGroups(
_ groups: [MobileWorkspaceGroupPreview],
macDeviceID: String,
instanceTag: String?
) -> [MobileWorkspaceGroupPreview] {
guard let macDeviceID = normalizedWorkspaceOwner(macDeviceID) else {
return []
}
return groups.filter { group in
guard let groupMacDeviceID = normalizedWorkspaceOwner(group.macDeviceID),
groupMacDeviceID == macDeviceID else {
return false
func filteredWorkspaceGroups(
_ groups: [MobileWorkspaceGroupPreview],
macDeviceID: String,
instanceTag: String?
) -> [MobileWorkspaceGroupPreview] {
guard let macDeviceID = normalizedWorkspaceOwner(macDeviceID) else {
return []
}
return groups.filter { group in
guard let groupMacDeviceID = normalizedWorkspaceOwner(group.macDeviceID),
groupMacDeviceID == macDeviceID else {
return false
}
return normalizedWorkspaceOwner(group.macInstanceTag) == normalizedWorkspaceOwner(instanceTag)
}
return normalizedWorkspaceOwner(group.macInstanceTag) == normalizedWorkspaceOwner(instanceTag)
}
}

private func normalizedWorkspaceOwner(_ value: String?) -> String? {
guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines),
!value.isEmpty else {
return nil
func normalizedWorkspaceOwner(_ value: String?) -> String? {
guard let value = value?.trimmingCharacters(in: .whitespacesAndNewlines),
!value.isEmpty else {
return nil
}
return value
}
return value
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ struct MobileInjectedAttachStartupTests {
of: MobilePairingURLConnectionResult.self
)

#expect(coordinator.startInjectedAttach(
let initialAttachStarted = coordinator.startInjectedAttach(
attachURL: attachURL,
prepare: {},
connect: { rawURL in
Expand All @@ -91,14 +91,15 @@ struct MobileInjectedAttachStartupTests {
onCompletion: { completion in
connectionFinished.continuation.yield(completion.result)
}
))
)
#expect(initialAttachStarted)

for await _ in connectionStarted.stream.prefix(1) {}

// A reconstructed root asks startup to run again. The app-lifetime
// coordinator must retain the original task and consume this duplicate
// request without starting a replacement connection.
#expect(coordinator.startInjectedAttach(
let duplicateAttachAccepted = coordinator.startInjectedAttach(
attachURL: attachURL,
prepare: {},
connect: { rawURL in
Expand All @@ -108,7 +109,8 @@ struct MobileInjectedAttachStartupTests {
onCompletion: { completion in
connectionFinished.continuation.yield(completion.result)
}
))
)
#expect(duplicateAttachAccepted)

allowConnectionToFinish.continuation.yield()
var results: [MobilePairingURLConnectionResult] = []
Expand Down
35 changes: 35 additions & 0 deletions Packages/macOS/CmuxFilePreviewSyntax/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// swift-tools-version: 6.0

import PackageDescription

let package = Package(
name: "CmuxFilePreviewSyntax",
platforms: [
.macOS(.v14),
],
products: [
.library(
name: "CmuxFilePreviewSyntax",
targets: ["CmuxFilePreviewSyntax"]
),
],
targets: [
.target(
name: "CmuxFilePreviewSyntax",
swiftSettings: [
.swiftLanguageMode(.v6),
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("InternalImportsByDefault"),
]
),
.testTarget(
name: "CmuxFilePreviewSyntaxTests",
dependencies: ["CmuxFilePreviewSyntax"],
swiftSettings: [
.swiftLanguageMode(.v6),
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("InternalImportsByDefault"),
]
),
]
)
Loading
Loading