mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
a8cdb3e663
Mirrors the v0.13 surfaces from WS-2 (Persistent Goals + ACP /queue),
WS-3 (Kanban diagnostics + hallucination gate), WS-4 (Curator archive),
and WS-5 (Google Chat platform + cross-platform allowlists + behavior
toggles) onto ScarfGo. Per Phase H precedent, every iOS surface is
strictly read-only — write verbs (Verify / Reject, /goal --clear, queue
send, allowlist editing, archive Restore / Prune) live on Mac in v2.8.0
and are deferred to v2.8.x.
Five iOS additions, all capability-gated so pre-v0.13 hosts see the
v2.7.5 layout unchanged:
1. Chat — goal pill ("Goal: <text>") and queue chip ("N queued") render
inside `projectContextBar` whenever a project, goal, or queue is
present. The bar is no longer project-only; goal/queue chips render
even outside a project chat. Goal text scales with Dynamic Type
(semantic `.subheadline`); the full untruncated text rides VoiceOver
via the chip's accessibility label.
2. Kanban — `ScarfGoKanbanDetailSheet` gains a `retries: N` chip in the
header `FlowLayout`, a yellow "Worker-created — verify on Mac" badge
for `pending` hallucination state, a red "Auto-blocked" banner with
the server-supplied `auto_blocked_reason`, and tappable diagnostics
chip-lists (task-level + per-run) that present a new
`DiagnosticDetailSheet` with kind / severity / message / timestamp.
No Verify or Reject buttons; the badge copy points users to the Mac
app.
3. Curator — `CuratorView` appends a read-only "Archived" section that
loads via `viewModel.loadArchive()` on appear and pull-to-refresh.
Per-row name + category badge + reason + archived-at + size; footer
signposts users to the Mac app for Restore / Prune.
4. Settings → Platforms — adds a Google Chat status row (configured /
not configured), busy-ack and restart-notification rows summarized
across `gatewayPlatforms` (yes / no / mixed (N platforms)), and
collapsed DisclosureGroups for allowed channels / chats / rooms with
monospaced "platform: id" entries when expanded. No editor.
5. Settings — green "v0.13 features active" `ScarfBadge` above the
quick-edits section when `caps.isV013OrLater`. Tap presents a new
`V013FeaturesSheet` listing the six v0.13 surfaces with one-sentence
summaries; the section footer is explicit that editing lives on Mac.
Implements WS-9 of Scarf v2.8.0 (Hermes v0.13.0 catch-up).
Plan: scarf/docs/v2.8/WS-9-ios-v0.13-plan.md (on coordination/v2.8.0-plans).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
3.1 KiB
Swift
87 lines
3.1 KiB
Swift
import SwiftUI
|
|
import ScarfCore
|
|
import ScarfDesign
|
|
|
|
/// iOS substitute for the Mac inspector's `.help()` tooltip on a Kanban
|
|
/// diagnostic chip. iOS doesn't have hover, so each diagnostic chip in
|
|
/// the detail sheet is tappable; tap presents this sheet with the kind,
|
|
/// severity, server-supplied message, and detection timestamp.
|
|
///
|
|
/// Read-only — there are no recovery actions on iOS in v2.8.0. The
|
|
/// surface is deliberately small (one screen, no scroll padding) so it
|
|
/// reads as a fast peek rather than a full editor.
|
|
struct DiagnosticDetailSheet: View {
|
|
let diagnostic: HermesKanbanDiagnostic
|
|
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
List {
|
|
Section {
|
|
LabeledContent("Kind") {
|
|
Text(diagnostic.kind)
|
|
.font(.body.monospaced())
|
|
.foregroundStyle(.primary)
|
|
}
|
|
LabeledContent("Severity") {
|
|
ScarfBadge(severityLabel, kind: severityBadgeKind)
|
|
}
|
|
if let detectedAt = diagnostic.detectedAt, !detectedAt.isEmpty {
|
|
LabeledContent("Detected at") {
|
|
Text(detectedAt)
|
|
.font(.caption.monospaced())
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
} header: {
|
|
Text("Diagnostic")
|
|
}
|
|
|
|
if let message = diagnostic.message, !message.isEmpty {
|
|
Section {
|
|
Text(message)
|
|
.font(.body)
|
|
.textSelection(.enabled)
|
|
} header: {
|
|
Text("Message")
|
|
}
|
|
}
|
|
|
|
Section {
|
|
Label("Recovery actions live on the Mac app — open this task there to verify, reject, or unblock.", systemImage: "info.circle")
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
.scrollContentBackground(.hidden)
|
|
.background(ScarfColor.backgroundPrimary)
|
|
.navigationTitle("Diagnostic")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Button("Done") { dismiss() }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private var severityLabel: String {
|
|
let kind = KanbanDiagnosticKind.from(diagnostic.kind)
|
|
switch kind.severity {
|
|
case .danger: return "danger"
|
|
case .warning: return "warning"
|
|
case .neutral: return "neutral"
|
|
}
|
|
}
|
|
|
|
private var severityBadgeKind: ScarfBadgeKind {
|
|
let kind = KanbanDiagnosticKind.from(diagnostic.kind)
|
|
switch kind.severity {
|
|
case .danger: return .danger
|
|
case .warning: return .warning
|
|
case .neutral: return .neutral
|
|
}
|
|
}
|
|
}
|