From 1f9818c50f4c679e4d03f388726bc487cd5a2e7f Mon Sep 17 00:00:00 2001 From: mptyl Date: Sat, 4 Jul 2026 14:21:57 +0200 Subject: [PATCH] fix(gate): guard the TUI-only "Esc" notice on ctx.mode, not ctx.hasUI reLoop's "Esc non chiude il gate..." warning is terminal-specific. On pi 0.73 ctx.hasUI was false in RPC, so `if (ctx.hasUI)` effectively meant "TUI only". On pi >=0.80 hasUI is true in RPC too (dialog-capable UI via the bridge), so the notice leaked to the browser on any invalid gate response. Guard on ctx.mode === "tui" to restore the original intent. The fake pi runtime gains mode:"tui" so the roundtrip test still exercises the notice. Audit of the other 5 ctx.ui.notify: left as-is. They are valid in both live modes (TUI and RPC, both hasUI=true) and the gate cannot run headless (emitAndWait needs a UI), so a guard would be dead code. Their dual-mode rationalization belongs with the future present() work (tracked in the eval doc). Co-Authored-By: Claude Opus 4.8 --- harness/.pi/extensions/gate/__tests__/fake_pi_runtime.js | 1 + harness/.pi/extensions/tht-gate.js | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/harness/.pi/extensions/gate/__tests__/fake_pi_runtime.js b/harness/.pi/extensions/gate/__tests__/fake_pi_runtime.js index a4c037b5..488ff155 100644 --- a/harness/.pi/extensions/gate/__tests__/fake_pi_runtime.js +++ b/harness/.pi/extensions/gate/__tests__/fake_pi_runtime.js @@ -6,6 +6,7 @@ function createFakePi() { const tools = new Map(); const ctx = { hasUI: true, + mode: "tui", cwd: "/tmp/fake-pi-session", notifications: [], uiCalls: [], diff --git a/harness/.pi/extensions/tht-gate.js b/harness/.pi/extensions/tht-gate.js index 83f78ca9..a36486e4 100644 --- a/harness/.pi/extensions/tht-gate.js +++ b/harness/.pi/extensions/tht-gate.js @@ -316,7 +316,10 @@ export async function emitAndWait(ctx, descriptor) { } async function reLoop(ctx) { - if (ctx.hasUI) + // TUI-only: "Esc"/terminal navigation has no meaning in RPC (the browser + // renders widget buttons). Guard on ctx.mode, NOT ctx.hasUI — on pi >=0.80 + // hasUI is true in RPC too, so this warning would leak to the frontend. + if (ctx.mode === "tui") await ctx.ui.notify( "Esc non chiude il gate: usa Torna indietro / Esci / Altro dalle opzioni.", "warning", @@ -648,7 +651,7 @@ export default function (pi) { const resp = await emitAndWait(ctx, widget); outcome = resolveConfirmOutcome(resp); if (outcome.kind !== "unknown") break; - await ctx.ui.notify("Scegli «Conferma e prosegui» o «Rifiuta».", "warning"); + await ctx.ui.notify("Scegli «Salva e procedi» o «Rifiuta».", "warning"); } if (outcome.kind === "freetext") return textResult(