fix(settings): restore flush_memories aux row on pre-v0.12 hosts

Phase B removed the `flushMemories` field from `AuxiliarySettings`,
the `aux("flush_memories")` reader from the YAML parser, and the
"Flush Memories" row from `AuxiliaryTab.tasks` outright. But
`HermesCapabilities.hasFlushMemoriesAux` still claims (with inverse
semantics) that the row should stay visible on pre-v0.12 hosts where
the task is alive. Project CLAUDE.md documents the same contract.

Restored:
- `AuxiliarySettings.flushMemories: AuxiliaryModel` (and `.empty`).
- `aux("flush_memories")` in both YAML readers
  (`HermesConfig+YAML.swift` and the `HermesFileService` mirror).
- `AuxiliaryTab.tasks` appends the Flush Memories row when
  `hasFlushMemoriesAux` is true, mirroring how `curator` is appended
  on the v0.12+ branch.

On v0.12+ hosts the flag is `false` so the field stays `.empty` and
the row is hidden — no behaviour change for current users.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-05-01 13:22:41 +02:00
parent 4a2ef74b74
commit 33022aeb92
4 changed files with 23 additions and 7 deletions
@@ -260,8 +260,11 @@ public struct VoiceSettings: Sendable, Equatable {
/// Per-task auxiliary model overrides.
///
/// `flush_memories` was removed entirely in Hermes v0.12 (the underlying
/// task no longer exists), so the corresponding field was dropped here.
/// `flush_memories` was removed in Hermes v0.12 but remains alive on
/// pre-v0.12 hosts the field is preserved here so the YAML parser
/// can round-trip it and `AuxiliaryTab` can render the row when
/// `HermesCapabilities.hasFlushMemoriesAux` is set. On v0.12+ the
/// field stays empty and is never surfaced.
/// `curator` was added in v0.12 Curator's review fork uses its own
/// model so users can keep main-model spend separate from background
/// maintenance.
@@ -273,6 +276,8 @@ public struct AuxiliarySettings: Sendable, Equatable {
public var skillsHub: AuxiliaryModel
public var approval: AuxiliaryModel
public var mcp: AuxiliaryModel
/// pre-v0.12 only; on v0.12+ this stays `.empty` and the row is hidden.
public var flushMemories: AuxiliaryModel
/// v0.12+; pre-v0.12 Hermes installs ignore this slot.
public var curator: AuxiliaryModel
@@ -285,6 +290,7 @@ public struct AuxiliarySettings: Sendable, Equatable {
skillsHub: AuxiliaryModel,
approval: AuxiliaryModel,
mcp: AuxiliaryModel,
flushMemories: AuxiliaryModel,
curator: AuxiliaryModel
) {
self.vision = vision
@@ -294,6 +300,7 @@ public struct AuxiliarySettings: Sendable, Equatable {
self.skillsHub = skillsHub
self.approval = approval
self.mcp = mcp
self.flushMemories = flushMemories
self.curator = curator
}
public nonisolated static let empty = AuxiliarySettings(
@@ -304,6 +311,7 @@ public struct AuxiliarySettings: Sendable, Equatable {
skillsHub: .empty,
approval: .empty,
mcp: .empty,
flushMemories: .empty,
curator: .empty
)
}
@@ -122,6 +122,7 @@ public extension HermesConfig {
skillsHub: aux("skills_hub"),
approval: aux("approval"),
mcp: aux("mcp"),
flushMemories: aux("flush_memories"),
curator: aux("curator")
)
@@ -129,6 +129,7 @@ struct HermesFileService: Sendable {
skillsHub: aux("skills_hub"),
approval: aux("approval"),
mcp: aux("mcp"),
flushMemories: aux("flush_memories"),
curator: aux("curator")
)
@@ -10,11 +10,13 @@ import ScarfCore
/// the gateway routing from that single field; there is no separate
/// `use_gateway` key to write.
///
/// v0.12 dropped the `flush_memories` aux task (the underlying memory
/// pipeline was rewritten upstream) and added `curator` (the autonomous
/// skill-maintenance review fork). The Curator row only appears when
/// `HermesCapabilities.hasCuratorAux` is set so v0.11 hosts don't see a
/// row that writes a key Hermes ignores.
/// v0.12 dropped the `flush_memories` aux task on the server side and
/// added `curator` (the autonomous skill-maintenance review fork). The
/// Curator row only appears when `HermesCapabilities.hasCuratorAux` is
/// set; the Flush Memories row only appears when
/// `HermesCapabilities.hasFlushMemoriesAux` is set (inverse semantics
/// `true` only on pre-v0.12 hosts where the task still exists). v0.11
/// users keep their edit surface; v0.12 users never see it.
struct AuxiliaryTab: View {
@Bindable var viewModel: SettingsViewModel
@@ -38,6 +40,9 @@ struct AuxiliaryTab: View {
private var tasks: [(key: String, title: LocalizedStringKey, icon: String)] {
var t = baseTasks
if capabilitiesStore?.capabilities.hasFlushMemoriesAux ?? false {
t.append(("flush_memories", "Flush Memories", "trash.slash"))
}
if capabilitiesStore?.capabilities.hasCuratorAux ?? false {
t.append(("curator", "Curator", "sparkles"))
}
@@ -110,6 +115,7 @@ struct AuxiliaryTab: View {
case "skills_hub": return viewModel.config.auxiliary.skillsHub
case "approval": return viewModel.config.auxiliary.approval
case "mcp": return viewModel.config.auxiliary.mcp
case "flush_memories": return viewModel.config.auxiliary.flushMemories
case "curator": return viewModel.config.auxiliary.curator
default: return .empty
}