fix(chat): drop forward-looking version labels + add /exit to alwaysAvailable

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) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-05-09 20:43:34 +02:00
parent 096dbe085e
commit e26acaff4e
2 changed files with 10 additions and 4 deletions
@@ -30,7 +30,7 @@ public struct HermesSlashCommand: Identifiable, Sendable, Equatable {
/// menu offer discoverable affordances like `/new` even before /// menu offer discoverable affordances like `/new` even before
/// the user has opened a session. Once a session starts, the /// the user has opened a session. Once a session starts, the
/// ACP-advertised version takes over (deduped by name in /// 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 case alwaysAvailable
} }
@@ -361,6 +361,12 @@ public final class RichChatViewModel {
description: "Show available commands", description: "Show available commands",
argumentHint: nil, argumentHint: nil,
source: .alwaysAvailable source: .alwaysAvailable
),
HermesSlashCommand(
name: "exit",
description: "End the current session",
argumentHint: nil,
source: .alwaysAvailable
) )
]) ])
return result return result
@@ -710,8 +716,8 @@ public final class RichChatViewModel {
// `session/new`); they don't change when the user switches // `session/new`); they don't change when the user switches
// sessions. Hermes does not re-emit on `session/load`, so if // sessions. Hermes does not re-emit on `session/load`, so if
// we wipe here, resumed sessions land at a 4-command fallback // we wipe here, resumed sessions land at a 4-command fallback
// until the user starts a fresh session exactly the dogfood // until the user starts a fresh session observed during
// bug surfaced during v2.8.0 testing. The caller paths // dogfooding against a Hermes v0.13 host. The caller paths
// (startNewSession, resumeSession, continueLastSession) all // (startNewSession, resumeSession, continueLastSession) all
// spawn a fresh ACP subprocess; if that subprocess emits a // spawn a fresh ACP subprocess; if that subprocess emits a
// fresh list, our value is replaced; if it doesn't, we keep // 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 // accurate as long as the agent identity hasn't changed. The
// host-switch case (Local SSH) tears down the whole // host-switch case (Local SSH) tears down the whole
// ContextBoundRoot so this stale carry-over isn't reachable // ContextBoundRoot so this stale carry-over isn't reachable
// there. See WS-2 / v2.8.0 dogfood report. // there.
projectScopedCommands = [] projectScopedCommands = []
currentTurnStart = nil currentTurnStart = nil
turnDurations = [:] turnDurations = [:]