Catches the Curator surface up to Hermes v0.13's new write-side verbs
(`archive <skill>`, `prune`, `list-archived`, synchronous `run`). Adds
a new `CuratorService` actor in ScarfCore mirroring `KanbanService`'s
pattern (Sendable, pure I/O, `Task.detached(priority: .utility)` per
verb), tolerantly-decoded `HermesCuratorArchivedSkill` /
`CuratorPruneSummary` models, and `CuratorError` for inline-banner
surfacing.
Mac UX gains an "Archived" section between the leaderboards and the
last-report block (per-row Restore button), an "archivebox" button on
every active-skill leaderboard row to manually archive, a destructive
"Prune Archived…" confirm sheet enumerating each skill (template-
uninstall pattern — Cancel owns `.defaultAction`, Prune is on the red
`ScarfDestructiveButton`), and a synchronous-with-progress "Run Now"
on v0.13+ hosts (600s timeout, `ProgressView` while in-flight).
Failure path routes through a yellow inline error banner instead of a
modal alert. The legacy `CuratorRestoreSheet` stays accessible from
the overflow menu but only on pre-v0.13 hosts; on v0.13+ the per-row
Restore in the new Archived section replaces it.
All new surfaces gate on `HermesCapabilities.hasCuratorArchive` —
pre-v0.13 hosts see the v2.7.x layout unchanged. iOS picks up the new
`runNow(synchronous:)` signature with the v0.13 capability flag; the
read-only Archived section + WS-9 marker is left for the next stream.
14 new parser tests in `HermesCuratorParserTests` cover the JSON
happy path, the `{"archived": [...]}` envelope, the text fallback
(`--json` not supported), `"no archived skills"` sentinel folding,
prune-dry-run with both wrapper + bare-array shapes, and zero-skill
prune. All 369 ScarfCore tests pass; `xcodebuild` for the `scarf`
scheme succeeds.
Wire-shape unknowns (CLI flag presence on real v0.13) carry
`// TODO(WS-4-Q<N>)` markers in `CuratorService` and fall back
defensively when a flag isn't recognized. Implements WS-4 of Scarf
v2.8.0 (Hermes v0.13.0 catch-up). Plan:
scarf/docs/v2.8/WS-4-curator-archive-plan.md (on
coordination/v2.8.0-plans).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hermes v0.12 ships an autonomous Curator that prunes / consolidates
agent-created skills on a 7-day cycle. This phase brings that surface
into Scarf so users can see status, trigger runs, pin protected skills,
and restore archived ones.
Pipeline:
- HermesCuratorStatus + HermesCuratorSkillRow: Sendable value types for
parsed status + per-skill leaderboard rows.
- HermesCuratorStatusParser: pure text parser for `hermes curator status`
stdout (no `--json` flag exists upstream). Tolerates Hermes's
whitespace-padded leaderboard layout (`activity= 0` with N spaces
between `=` and the value) by slicing between known key positions
rather than splitting on whitespace. State-file JSON overrides
text-parsed values for last_run_at / last_run_summary /
last_report_path because the file carries full ISO timestamps the
text output may have rounded.
- CuratorViewModel: @Observable @MainActor, drives the CLI verbs
(status / run / pause / resume / pin / unpin / restore) via
transport.runProcess so it works equally over local and Citadel SSH.
- HermesPathSet: adds curatorLogsDir + curatorStateFile (the latter
is `.curator_state` with no extension despite holding JSON).
Mac:
- Features/Curator/Views/CuratorView.swift — page-header + status card
+ skill counts + pinned chips + 3 leaderboard tables (least recent,
most active, least active) with inline pin toggles and a
per-skill counter chip row. "Run Now" button + a kebab menu for
Pause/Resume + Restore Archived.
- Features/Curator/Views/CuratorRestoreSheet.swift — name-entry sheet
for `hermes curator restore <skill>`. Free-form text field; Hermes
doesn't ship a `curator list-archived` yet so we don't synthesize a
picker.
- Sidebar: AppCoordinator + SidebarView gain a `.curator` case under
Interact (between Memory and Skills); the row is filtered out by
SidebarView's capability-aware `sections` computed property when
`HermesCapabilities.hasCurator` is false. ContentView routes
`.curator` to CuratorView. Pre-v0.12 hosts see the v0.11 sidebar
unchanged.
iOS:
- Scarf iOS/Curator/CuratorView.swift — read-mostly List with the same
status / skill counts / pinned / leaderboards + inline pin toggles.
Run Now / Pause / Resume actions in the section footer.
- ScarfGoTabRoot's System tab gains a Curator NavigationLink under
Features, gated on `hasCurator`. Uses a stable
`systemTabContextID` so the SSH transport pool reuses the cached
Citadel connection keyed by that id.
Tests: 6 new parser tests (215 total, all green). Locks the empty-state
output captured from a real v0.12.0 install + paused-state + state-file
override + multi-word-name-row parsing. Both Mac and iOS schemes build
clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>