From 963d0e1a5cb04d2eb70b1a315343fc7e1cd44e14 Mon Sep 17 00:00:00 2001 From: Alan Wizemann Date: Sat, 9 May 2026 18:08:14 +0200 Subject: [PATCH] feat(capabilities): add isV013OrLater convenience predicate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surfaces a v0.12 → v0.13 boundary check that doesn't proxy through any specific feature flag. Used by WS-8 (redaction default-state hint copy, "v0.13 features active" Settings badge in iOS WS-9) where the call site isn't actually about a specific feature — it's about whether the host is on the v0.13 line. Equivalent to any individual v0.13 flag (e.g. `hasGoals`); both resolve to the same `>= 0.13.0` threshold. Convenience exists to keep call sites honest: `caps.isV013OrLater` reads better than `caps.hasGoals` when the context isn't goal-related. Tests: 4 new fixtures covering v0.13 host (true), v0.12 host (false), empty/undetected (false), and v0.14 host (true). 19 total tests in the suite, all passing. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Services/HermesCapabilities.swift | 10 +++++++++ .../HermesCapabilitiesTests.swift | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/scarf/Packages/ScarfCore/Sources/ScarfCore/Services/HermesCapabilities.swift b/scarf/Packages/ScarfCore/Sources/ScarfCore/Services/HermesCapabilities.swift index 9c408fb..f9498d0 100644 --- a/scarf/Packages/ScarfCore/Sources/ScarfCore/Services/HermesCapabilities.swift +++ b/scarf/Packages/ScarfCore/Sources/ScarfCore/Services/HermesCapabilities.swift @@ -210,6 +210,16 @@ public struct HermesCapabilities: Sendable, Equatable { /// PluginsView surfaces it as a documented hook in plugin metadata. public var hasTransformLLMOutputHook: Bool { atLeastSemver(0, 13, 0) } + // MARK: Convenience predicates + + /// Whether the connected host is on the v0.13 line or newer. Convenience + /// for UI copy that needs to switch on the v0.12 → v0.13 boundary without + /// proxying through a feature-specific flag (e.g. "v0.13 features active" + /// badges, redaction default-state hints). Equivalent to any individual + /// v0.13 flag; prefer this when the call site isn't actually about a + /// specific feature. + public var isV013OrLater: Bool { atLeastSemver(0, 13, 0) } + private func atLeastSemver(_ major: Int, _ minor: Int, _ patch: Int) -> Bool { guard let s = semver else { return false } return s >= SemVer(major: major, minor: minor, patch: patch) diff --git a/scarf/Packages/ScarfCore/Tests/ScarfCoreTests/HermesCapabilitiesTests.swift b/scarf/Packages/ScarfCore/Tests/ScarfCoreTests/HermesCapabilitiesTests.swift index ab2824a..929d350 100644 --- a/scarf/Packages/ScarfCore/Tests/ScarfCoreTests/HermesCapabilitiesTests.swift +++ b/scarf/Packages/ScarfCore/Tests/ScarfCoreTests/HermesCapabilitiesTests.swift @@ -202,4 +202,26 @@ import Foundation #expect(caps.hasKanbanDiagnostics) #expect(caps.hasGoogleChatPlatform) } + + // MARK: - isV013OrLater convenience predicate + + @Test func isV013OrLater_v013HostTrue() { + let caps = HermesCapabilities.parseLine("Hermes Agent v0.13.0 (2026.5.7)") + #expect(caps.isV013OrLater) + } + + @Test func isV013OrLater_v012HostFalse() { + let caps = HermesCapabilities.parseLine("Hermes Agent v0.12.0 (2026.4.30)") + #expect(!caps.isV013OrLater) + } + + @Test func isV013OrLater_emptyFalse() { + let caps = HermesCapabilities.empty + #expect(!caps.isV013OrLater) + } + + @Test func isV013OrLater_v014HostTrue() { + let caps = HermesCapabilities.parseLine("Hermes Agent v0.14.0 (2026.7.1)") + #expect(caps.isV013OrLater) + } }