From 629f4690fe56db830632663eeca6741a6a4acf99 Mon Sep 17 00:00:00 2001 From: Nucleic Date: Tue, 21 Jul 2026 18:47:59 -0700 Subject: [PATCH] Merge nucleic/calm-north-ferret-9vca into dev --- .../NucleicRemote/Views/ApprovalCardView.swift | 14 ++++++++++---- .../Views/Transcript/SandboxToolDisplay.swift | 8 ++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/NucleicRemote/NucleicRemote/Views/ApprovalCardView.swift b/NucleicRemote/NucleicRemote/Views/ApprovalCardView.swift index 1d3d709..9b019ab 100644 --- a/NucleicRemote/NucleicRemote/Views/ApprovalCardView.swift +++ b/NucleicRemote/NucleicRemote/Views/ApprovalCardView.swift @@ -23,7 +23,10 @@ struct ApprovalCardView: View { Text("Permission requested").font(.subheadline.weight(.semibold)) } HStack(spacing: 6) { - Text(approval.toolName).font(.caption.weight(.bold)) + // The gate reads as what it grants — "macOS VM", "linux_container" — rather than + // as the `mcp__nucleic__…` wire name, matching the Mac's approval header. + Text(SandboxToolDisplay.gateLabel(for: approval.toolName)) + .font(.caption.weight(.bold)) Text(approval.risk.label) .font(.caption2.weight(.semibold)) .padding(.horizontal, 6).padding(.vertical, 2) @@ -148,10 +151,13 @@ struct ApprovalCardView: View { } private func alwaysLabel(_ scope: AlwaysScope) -> String { + // Named the same way the header names it — the rule still matches on the exact tool name; + // only how it's spelled to the user changes. + let tool = SandboxToolDisplay.gateLabel(for: approval.toolName) switch scope { - case .session: "This command, this session" - case .toolName: "Any \(approval.toolName), this session" - case .toolNameWithPattern: "\(approval.toolName) matching this pattern" + case .session: return "This command, this session" + case .toolName: return "Any \(tool), this session" + case .toolNameWithPattern: return "\(tool) matching this pattern" } } } diff --git a/NucleicRemote/NucleicRemote/Views/Transcript/SandboxToolDisplay.swift b/NucleicRemote/NucleicRemote/Views/Transcript/SandboxToolDisplay.swift index d49fd3c..cceaf33 100644 --- a/NucleicRemote/NucleicRemote/Views/Transcript/SandboxToolDisplay.swift +++ b/NucleicRemote/NucleicRemote/Views/Transcript/SandboxToolDisplay.swift @@ -38,6 +38,14 @@ enum SandboxToolDisplay { } } + /// The tool name for an *approval* surface, where identity is what the user is deciding on: + /// the pretty label when we have one, and otherwise the tool name with the `mcp__nucleic__` + /// plumbing prefix dropped. Never nil and never invented — a tool this file doesn't know + /// still reads as its own identifier rather than as something friendlier than it is. + static func gateLabel(for toolName: String) -> String { + label(for: toolName) ?? bareName(toolName) + } + /// SF Symbol for the tool — a screen for computer-use, a box for a container, a power switch /// for a lifecycle op — so the glyph carries the same distinction the label does. static func icon(for toolName: String) -> String? {