From 654f96f9c1d3ee80afc3034a883cb9083caefe00 Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Fri, 7 Aug 2026 14:00:18 -0500 Subject: [PATCH 1/3] feat: add Xcode companion workspace model --- .github/workflows/ci.yml | 17 ++++++ README.md | 16 ++++- Sources/ZedCore/ZedWorkspaceModel.swift | 59 +++++++++++++++++++ .../ZedCoreTests/ZedWorkspaceModelTests.swift | 32 ++++++++++ conformance/ide-integration.json | 23 ++++++++ 5 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 Sources/ZedCore/ZedWorkspaceModel.swift create mode 100644 Tests/ZedCoreTests/ZedWorkspaceModelTests.swift create mode 100644 conformance/ide-integration.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..112fb8b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,17 @@ +name: ci + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + swift: + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + - run: swift test + - run: swift build -c release diff --git a/README.md b/README.md index a4cf4d7..3c0d6a6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,17 @@ # zed-xcode -Buildable Swift core candidate for a macOS companion app and Xcode Source Editor Extension. +Native Apple integration work for Zed Package Manager state, diagnostics, and confirmation-gated recommended actions. -The core has an injectable process runner, argv execution, timeout, schema validation, output redaction, and unsafe-action rejection. `swift test` covers the contract without launching a user's Xcode instance. +The Swift package now contains: -A dedicated repository still needs the companion dashboard, XcodeKit commands, signed app/appex packaging, entitlements, and clean Xcode-instance UI tests. +- an injectable `zed inspect` process boundary with timeout, schema validation, redaction, and unsafe-action rejection; +- a multi-root workspace projection suitable for a SwiftUI companion dashboard; +- confirmation-gated command previews carrying exact executable, argv, and working directory; +- unit tests that run without launching or mutating a user's Xcode instance. + +```sh +swift test +swift build -c release +``` + +The dedicated repository is established. Remaining distribution work is the SwiftUI companion app target, XcodeKit Source Editor Extension, App Group cache and entitlements, clean Xcode-instance tests, signing/notarization, and app/appex packaging. diff --git a/Sources/ZedCore/ZedWorkspaceModel.swift b/Sources/ZedCore/ZedWorkspaceModel.swift new file mode 100644 index 0000000..05a8a86 --- /dev/null +++ b/Sources/ZedCore/ZedWorkspaceModel.swift @@ -0,0 +1,59 @@ +import Foundation + +public struct ZedPackageSnapshot: Sendable, Equatable { + public let root: String + public let errors: Int + public let warnings: Int + public let issues: [ZedIssue] + + public init(root: String, errors: Int, warnings: Int, issues: [ZedIssue]) { + self.root = root + self.errors = errors + self.warnings = warnings + self.issues = issues + } + + public static func == (lhs: Self, rhs: Self) -> Bool { + lhs.root == rhs.root && lhs.errors == rhs.errors && lhs.warnings == rhs.warnings && lhs.issues.map(\.id) == rhs.issues.map(\.id) + } +} + +public struct ZedActionPreview: Sendable, Equatable { + public let executable: String + public let arguments: [String] + public let workingDirectory: String + public let requiresConfirmation: Bool +} + +public enum ZedWorkspaceModelError: Error, Equatable { + case nonCommandAction + case confirmationRequired + case missingExecutable +} + +public enum ZedWorkspaceModel { + public static func project(_ reports: [ZedReport]) -> [ZedPackageSnapshot] { + reports.map { report in + let errors = report.issues.filter { $0.severity.lowercased() == "error" }.count + let warnings = report.issues.filter { $0.severity.lowercased() == "warning" }.count + return ZedPackageSnapshot( + root: URL(fileURLWithPath: report.workspaceRoot).standardizedFileURL.path, + errors: errors, + warnings: warnings, + issues: report.issues + ) + }.sorted { $0.root < $1.root } + } + + public static func preview(action: ZedAction, root: String) throws -> ZedActionPreview { + guard action.kind == "command" else { throw ZedWorkspaceModelError.nonCommandAction } + guard action.requiresConfirmation else { throw ZedWorkspaceModelError.confirmationRequired } + guard !action.command.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { throw ZedWorkspaceModelError.missingExecutable } + return ZedActionPreview( + executable: action.command, + arguments: action.arguments, + workingDirectory: URL(fileURLWithPath: root).standardizedFileURL.path, + requiresConfirmation: true + ) + } +} diff --git a/Tests/ZedCoreTests/ZedWorkspaceModelTests.swift b/Tests/ZedCoreTests/ZedWorkspaceModelTests.swift new file mode 100644 index 0000000..4446739 --- /dev/null +++ b/Tests/ZedCoreTests/ZedWorkspaceModelTests.swift @@ -0,0 +1,32 @@ +import Foundation +import Testing +@testable import ZedCore + +@Test func projectsMultiRootReportsInStableOrder() { + let reports = [ + ZedReport(schemaVersion: 1, workspaceRoot: "/zeta", zedVersion: "0.1", issues: [ + ZedIssue(id: "lock.stale", severity: "warning", title: "Stale", detail: "", files: [], actions: []) + ]), + ZedReport(schemaVersion: 1, workspaceRoot: "/alpha", zedVersion: "0.1", issues: [ + ZedIssue(id: "manifest.invalid", severity: "error", title: "Invalid", detail: "", files: [], actions: []) + ]) + ] + let snapshots = ZedWorkspaceModel.project(reports) + #expect(snapshots.map(\.root) == ["/alpha", "/zeta"]) + #expect(snapshots[0].errors == 1) + #expect(snapshots[1].warnings == 1) +} + +@Test func previewsOnlyConfirmationGatedCommands() throws { + let action = ZedAction(id: "install", title: "Install", kind: "command", command: "zed", arguments: ["install"], requiresConfirmation: true) + let preview = try ZedWorkspaceModel.preview(action: action, root: "/tmp/work") + #expect(preview.executable == "zed") + #expect(preview.arguments == ["install"]) + #expect(preview.requiresConfirmation) + #expect(throws: ZedWorkspaceModelError.confirmationRequired) { + try ZedWorkspaceModel.preview( + action: ZedAction(id: "bad", title: "Bad", kind: "command", command: "zed", arguments: ["install"], requiresConfirmation: false), + root: "/tmp/work" + ) + } +} diff --git a/conformance/ide-integration.json b/conformance/ide-integration.json new file mode 100644 index 0000000..74e6443 --- /dev/null +++ b/conformance/ide-integration.json @@ -0,0 +1,23 @@ +{ + "schema": "zed-pkg/ide-integration-conformance/v1", + "integration": "xcode", + "repository": "zed-pkg/zed-xcode", + "contractVersion": 1, + "level": {"core": "pass", "nativeShell": "companion-model", "distribution": "repository"}, + "capabilities": { + "multiRootDiscovery": "workspace-model", + "manifestDiagnostics": true, + "lockDiagnostics": true, + "materializationDiagnostics": true, + "stagingRecovery": true, + "argvExecution": true, + "boundedExecution": true, + "outputRedaction": true, + "explicitMutationConfirmation": true, + "versionedInspectAdapter": "pending-zed-cli-191", + "nativeUnitTests": true, + "repoLocalCI": true + }, + "remaining": ["SwiftUI companion app target", "XcodeKit Source Editor Extension", "App Group cache/entitlements", "clean Xcode instance test", "signed app/appex packaging"], + "linearIssue": "DEN-2508" +} From e7e7030fa44496c14de7da684772c4113cfdd92f Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Fri, 7 Aug 2026 22:58:42 -0500 Subject: [PATCH 2/3] ci: pin Xcode workflow inputs --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 112fb8b..69c479d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,11 @@ permissions: jobs: swift: - runs-on: macos-latest + runs-on: macos-15 + timeout-minutes: 15 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - run: swift test - run: swift build -c release From 9b9304fee2ff236fc59407ddd97cc2c01225a69d Mon Sep 17 00:00:00 2001 From: Alexander Mills Date: Fri, 7 Aug 2026 23:17:54 -0500 Subject: [PATCH 3/3] docs: record immutable Xcode CI conformance --- conformance/ide-integration.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/conformance/ide-integration.json b/conformance/ide-integration.json index 74e6443..460fb4c 100644 --- a/conformance/ide-integration.json +++ b/conformance/ide-integration.json @@ -16,7 +16,10 @@ "explicitMutationConfirmation": true, "versionedInspectAdapter": "pending-zed-cli-191", "nativeUnitTests": true, - "repoLocalCI": true + "repoLocalCI": true, + "immutableWorkflowInputs": true, + "fixedRunnerImages": true, + "checkoutCredentialsPersisted": false }, "remaining": ["SwiftUI companion app target", "XcodeKit Source Editor Extension", "App Group cache/entitlements", "clean Xcode instance test", "signed app/appex packaging"], "linearIssue": "DEN-2508"