GitHub Issue

RFC: one gated actions core for GUI + MCP (ticket-minted policy, parse-once reports, frozen wire format)

Discovered On Jun 11, 2026
Primary Metric open
## Problem The same user-facing operation — "clean caches, maybe elevated, report freed bytes" — exists as **two parallel implementations in two processes**: - **GUI path:** `CleanView`/`OptimizeView` → `guarded()` FDA checks + confirm dialogs + `pendingRun` closure parking → `CommandRunner` → `TaskReport.parse` → `OperationCenter.begin/detail/end`. `SoftwareView` hand-rolls the uninstall flow (confirm sheet, dry-run match preflight, `"y\n"` stdin answers) separately. - **MCP path (separate process):** `ToolCatalog.callClean/callOptimize/callUninstall` re-spell the argv/stdin/timeouts, gate via `realActionAllowed()` (`confirm && Store.mcpActionsEnabled`), and return **raw unparsed text**. Purge/installer are preview-only with a hand-built redirect note. Consequences: - The argv tables, stdin scripts, and timeouts are spelled independently per surface and have already drifted (GUI uninstall 300 s vs MCP 600 s). - Gating folklore lives in scattered ifs and comments: "root bypasses TCC for cache walks but not for Downloads/Desktop", "optimize's auth prompt *is* the consent", "uninstall needs the second opt-in switch". None of the GUI policy is unit-testable — it's trapped in SwiftUI closures. - The uninstall **match preflight** (dry-run → pin mo's matched set → fail closed on divergence) exists twice and can half-regress. - The stream parser runs only in the GUI; agents get text. The freed-bytes summary the GUI banner shows and the text MCP returns can disagree. - The MCP wi...
View Raw Thread