From e26acaff4e6304c3271e0e1525fc611fed6c36ae Mon Sep 17 00:00:00 2001 From: Alan Wizemann Date: Sat, 9 May 2026 20:43:34 +0200 Subject: [PATCH] fix(chat): drop forward-looking version labels + add /exit to alwaysAvailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two follow-ups from code review on this branch: 1. Drop forward-looking Scarf version labels per the `feedback_no_version_bumps.md` rule (release notes own version labels, not in-code comments). "Added v2.8 alongside Hermes v0.13." becomes "Introduced alongside Hermes v0.13." on `HermesSlashCommand.Source.alwaysAvailable`. The `reset()` explanatory block in `RichChatViewModel` drops the two "v2.8.0" references — the rationale is unchanged, just stops marking the change with a Scarf-side version it might never ship under. 2. Add `/exit` to the active-session-only fallback set so the implementation matches the doc comment. The doc listed eight commands (`/clear`, `/compact`, `/cost`, `/model`, `/tools`, `/reload-skills`, `/help`, `/exit`) but only seven were appended. Adding `/exit` is the right call since it's a real Hermes ACP command; users typing `/exit` on a resumed session will now discover and dispatch it before the ACP-advertised version arrives. Tests: M9SlashCommandTests 30/30 green, Mac scheme builds clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ScarfCore/Models/HermesSlashCommand.swift | 2 +- .../ScarfCore/ViewModels/RichChatViewModel.swift | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/scarf/Packages/ScarfCore/Sources/ScarfCore/Models/HermesSlashCommand.swift b/scarf/Packages/ScarfCore/Sources/ScarfCore/Models/HermesSlashCommand.swift index 99a99cb..5c94884 100644 --- a/scarf/Packages/ScarfCore/Sources/ScarfCore/Models/HermesSlashCommand.swift +++ b/scarf/Packages/ScarfCore/Sources/ScarfCore/Models/HermesSlashCommand.swift @@ -30,7 +30,7 @@ public struct HermesSlashCommand: Identifiable, Sendable, Equatable { /// menu offer discoverable affordances like `/new` even before /// the user has opened a session. Once a session starts, the /// ACP-advertised version takes over (deduped by name in - /// `availableCommands`). Added v2.8 alongside Hermes v0.13. + /// `availableCommands`). Introduced alongside Hermes v0.13. case alwaysAvailable } diff --git a/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift b/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift index 8895db0..95150b8 100644 --- a/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift +++ b/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift @@ -361,6 +361,12 @@ public final class RichChatViewModel { description: "Show available commands", argumentHint: nil, source: .alwaysAvailable + ), + HermesSlashCommand( + name: "exit", + description: "End the current session", + argumentHint: nil, + source: .alwaysAvailable ) ]) return result @@ -710,8 +716,8 @@ public final class RichChatViewModel { // `session/new`); they don't change when the user switches // sessions. Hermes does not re-emit on `session/load`, so if // we wipe here, resumed sessions land at a 4-command fallback - // until the user starts a fresh session — exactly the dogfood - // bug surfaced during v2.8.0 testing. The caller paths + // until the user starts a fresh session — observed during + // dogfooding against a Hermes v0.13 host. The caller paths // (startNewSession, resumeSession, continueLastSession) all // spawn a fresh ACP subprocess; if that subprocess emits a // fresh list, our value is replaced; if it doesn't, we keep @@ -719,7 +725,7 @@ public final class RichChatViewModel { // accurate as long as the agent identity hasn't changed. The // host-switch case (Local → SSH) tears down the whole // ContextBoundRoot so this stale carry-over isn't reachable - // there. See WS-2 / v2.8.0 dogfood report. + // there. projectScopedCommands = [] currentTurnStart = nil turnDurations = [:]