Skip to content

[codex] Explain one-shot exec approval prompts#97081

Closed
NianJiuZst wants to merge 1 commit into
openclaw:mainfrom
NianJiuZst:codex/fix-exec-approval-unavailable-reason
Closed

[codex] Explain one-shot exec approval prompts#97081
NianJiuZst wants to merge 1 commit into
openclaw:mainfrom
NianJiuZst:codex/fix-exec-approval-unavailable-reason

Conversation

@NianJiuZst

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #97069.

Redirected or otherwise non-persistable exec commands such as openclaw --version 2>&1 can correctly hide Allow Always, but the prompt blamed the effective approval policy. That made ask=on-miss look like ask=always even though the hidden button was caused by one-shot command persistence safety.

Why This Change Was Made

The exec approval request only carried unavailableDecisions: ["allow-always"], so Control UI, forwarded chat approvals, native/reaction prompts, and gateway resolve errors could not tell whether Allow Always was hidden by policy or because the command could not be safely persisted.

This adds a typed allowAlwaysUnavailableReason and threads it through the gateway protocol, exec hosts, pending tool details, approval view model, forwarded/native rendering, reaction metadata, and i18n copy. Codex upstream was checked in ../codex/codex-rs/app-server-protocol/src/protocol/common.rs and ../codex/codex-rs/app-server-protocol/src/protocol/v2/item.rs; the upstream app-server approval params do not carry OpenClaw Allow Always persistence reasons, so this stays in OpenClaw's gateway approval protocol and renderers.

User Impact

Users still get the same safe one-shot behavior for redirected/non-persistable commands, but the prompt now explains that the command cannot be safely saved as an Allow Always rule instead of incorrectly saying the effective approval policy requires approval every time.

Evidence

  • node scripts/run-vitest.mjs packages/gateway-protocol/src/exec-approvals-validators.test.ts src/infra/exec-approvals-policy.test.ts src/gateway/server-methods/server-methods.test.ts src/infra/exec-approval-reply.test.ts src/infra/exec-approval-forwarder.test.ts ui/src/ui/controllers/exec-approval.test.ts ui/src/ui/views/exec-approval.test.ts src/agents/bash-tools.exec-host-gateway.test.ts src/agents/bash-tools.exec-host-node.test.ts src/plugin-sdk/approval-reaction-runtime.test.ts src/plugin-sdk/approval-renderers.test.ts src/agents/embedded-agent-subscribe.handlers.tools.test.ts src/infra/approval-view-model.test.ts passed 6 Vitest shards in 34.98s.
  • pnpm ui:i18n:check passed.
  • pnpm changed:lanes --json reported core, coreTests, extensions, and extensionTests lanes.
  • env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 OPENCLAW_CHANGED_LANES_RAW_SYNC=1 CI=1 PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false corepack pnpm check:changed passed guards and core/core-test/extensions/extension-test typechecks; it was interrupted during core lint so this PR could be pushed at maintainer request.
  • .agents/skills/autoreview/scripts/autoreview --mode local reported clean: no accepted/actionable findings.
  • Remote Testbox delegation via pnpm check:changed was blocked locally because Crabbox 0.18.0 is below the blacksmith-testbox minimum of 0.22.0.

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui gateway Gateway runtime agents Agent runtime and tooling size: L labels Jun 26, 2026
@NianJiuZst
NianJiuZst marked this pull request as ready for review June 26, 2026 18:35
@clawsweeper

clawsweeper Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 27, 2026, 3:39 PM ET / 19:39 UTC.

Summary
The PR adds an optional exec approval Allow Always unavailable reason across the gateway protocol, exec hosts, approval view model, shared renderers, Control UI parsing/rendering, tests, and Control UI i18n fallback metadata.

PR surface: Source +228, Tests +127. Total +355 across 65 files.

Reproducibility: yes. Source inspection and Mantis evidence show the current PR head still omits the new reason from Telegram approval payload construction, so the Telegram prompt reproduces the old policy wording for redirected non-persistable commands.

Review metrics: 1 noteworthy metric.

  • Approval reason surface: 1 gateway protocol field and 1 public approval reply parameter added. The new optional reason crosses protocol and SDK renderer boundaries, so every transport renderer must be checked before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #97069
Summary: This PR is a candidate fix for the canonical redirected-command Allow Always unavailable-copy bug; several sibling PRs overlap but none has merged as the canonical proof-positive fix.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦪 silver shellfish
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Pass the unavailable reason through Telegram native and forwarding payload builders.
  • [P1] Add focused Telegram regression coverage for non-persistable Allow Always copy.
  • Rerun Telegram Desktop proof on the repaired head.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The linked Mantis Telegram Desktop proof for the current head reports candidate failure; after repairing the payload path, contributors or maintainers should add redacted passing proof and update the PR body to trigger re-review.

Mantis proof suggestion
A native Telegram Desktop prompt directly shows whether the corrected unavailable reason reaches users. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis telegram desktop proof: verify that a redirected command approval hides Allow Always and explains that the command cannot be safely saved.

Risk before merge

  • [P1] The current head fails the Telegram-visible proof path: native Telegram approval prompts still receive no unavailable reason and fall back to the old policy wording.
  • [P1] GitHub currently reports the PR as conflicting, so the branch needs a refresh before any merge decision even after the functional repair.
  • [P1] Multiple open PRs target the same linked bug; maintainers still need one canonical fix before closing the cluster.

Maintainer options:

  1. Repair Telegram payload plumbing (recommended)
    Pass allowAlwaysUnavailableReason into Telegram native and forwarding payload builders, add focused Telegram regression coverage, and rerun native Telegram proof before merge.
  2. Choose another canonical candidate
    If maintainers prefer a different open branch for the linked bug, leave this PR unmerged and close it only after that candidate lands with proof.

Next step before merge

  • [P1] The PR needs author or maintainer follow-up plus fresh visible proof; repair automation should not be marked as the path because the external real-behavior proof gate remains unsatisfied.

Security
Cleared: The diff changes approval context propagation, prompt copy, tests, and generated i18n metadata without adding dependency, workflow, secret, package-resolution, download, or install/build execution changes.

Review findings

  • [P2] Pass the reason into Telegram approval payloads — extensions/telegram/src/approval-handler.runtime.ts:75-92
Review details

Best possible solution:

Keep one canonical fix that carries the unavailable reason into every visible approval renderer, including Telegram native and forwarding payloads, then require a passing Telegram Desktop proof on the final head.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection and Mantis evidence show the current PR head still omits the new reason from Telegram approval payload construction, so the Telegram prompt reproduces the old policy wording for redirected non-persistable commands.

Is this the best way to solve the issue?

No. A typed unavailable reason is the right fix shape, but this implementation is incomplete until the reason is passed through Telegram native and forwarding payload builders and verified with real Telegram proof.

Full review comments:

  • [P2] Pass the reason into Telegram approval payloads — extensions/telegram/src/approval-handler.runtime.ts:75-92
    The PR adds allowAlwaysUnavailableReason to the shared approval view and reply helper, but this Telegram native builder still calls buildExecApprovalPendingReplyPayload without passing that field, so the helper falls back to the policy wording. The Telegram forwarding builder has the same omission, and the Mantis run at this head confirms the visible prompt still shows the old text.
    Confidence: 0.93

Overall correctness: patch is incorrect
Overall confidence: 0.93

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c52adf7505a7.

Label changes

Label justifications:

  • P2: This is a bounded approval prompt correctness bug with limited blast radius, but the PR currently fails a user-visible Telegram proof path.
  • merge-risk: 🚨 other: Merging this PR as-is would ship a visible approval-copy fix that is known not to reach Telegram native approval prompts at the current head.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The linked Mantis Telegram Desktop proof for the current head reports candidate failure; after repairing the payload path, contributors or maintainers should add redacted passing proof and update the PR body to trigger re-review.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. This PR changes visible Telegram approval prompt copy, so a short Telegram Desktop proof should demonstrate the final behavior.
Evidence reviewed

PR surface:

Source +228, Tests +127. Total +355 across 65 files.

View PR surface stats
Area Files Added Removed Net
Source 55 314 86 +228
Tests 10 131 4 +127
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 65 445 90 +355

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs extensions/telegram/src/approval-handler.runtime.test.ts extensions/telegram/src/exec-approval-forwarding.test.ts src/infra/exec-approval-reply.test.ts src/infra/approval-view-model.test.ts.
  • [P1] pnpm ui:i18n:check.
  • [P1] Mantis Telegram Desktop proof for redirected command approval at the final head.

What I checked:

  • Repository policy applied: Root AGENTS.md and relevant scoped guides were read; Telegram maintainer notes require real Telegram proof for transport-visible approval behavior, and the plugin SDK guide treats approval renderer surface changes as public-contract sensitive. (AGENTS.md:1, c52adf7505a7)
  • Current main still collapses reasons: Current main removes allow-always for both ask === "always" and one-shot persistence, so allowed decisions alone cannot distinguish policy from non-persistable command shape. (src/infra/exec-approvals.ts:1824, c52adf7505a7)
  • PR head adds the reason to the view: At the PR head, the approval view model copies request.request.allowAlwaysUnavailableReason into the exec approval view, making the reason available to native approval renderers if they pass it on. (src/infra/approval-view-model.ts:75, 4588eb88a160)
  • Telegram native path still drops the reason: At the PR head, buildPendingPayload calls buildExecApprovalPendingReplyPayload with command, host, node, allowed decisions, and expiry, but without allowAlwaysUnavailableReason; the shared helper therefore falls back to the policy wording for native Telegram prompts. (extensions/telegram/src/approval-handler.runtime.ts:75, 4588eb88a160)
  • Telegram forwarding path still drops the reason: At the PR head, buildTelegramExecApprovalPendingPayload also calls buildExecApprovalPendingReplyPayload without the new reason, so forwarded Telegram approval prompts have the same gap. (extensions/telegram/src/exec-approval-forwarding.ts:34, 4588eb88a160)
  • Real proof failed at the current PR head: Live PR comments include Mantis Telegram Desktop proof for candidate 4588eb88a160ad8c0f1dd1ed817c6f3c16d3d6fa reporting that the candidate still shows the same old Allow Always unavailable wording. (4588eb88a160)

Likely related people:

  • jesse-merhi: The non-persistable command behavior and authorization planner changes trace to c9707ab635b9, which touched src/infra/exec-approvals.ts and both exec host paths. (role: one-shot persistence feature-history owner; confidence: high; commits: c9707ab635b9, 42f0822bfac9; files: src/infra/exec-approvals.ts, src/agents/bash-tools.exec-host-gateway.ts, src/agents/bash-tools.exec-host-node.ts)
  • gumadeiras: The generic Allow Always unavailable policy copy and related effective-policy approval reporting path trace to ba735d015809. (role: introduced effective-policy approval reporting path; confidence: high; commits: ba735d015809; files: src/infra/exec-approval-reply.ts, src/infra/exec-approval-forwarder.ts, src/infra/exec-approvals-effective.ts)
  • Bartok: Current checkout blame for the relevant approval helper and Telegram approval builder lines points at 4d9cd7d22755, a broad recent agents truncation change in the shallow history. (role: recent current-main line provenance; confidence: low; commits: 4d9cd7d22755; files: src/infra/exec-approvals.ts, src/infra/exec-approval-reply.ts, extensions/telegram/src/approval-handler.runtime.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jun 26, 2026
@openclaw-mantis

Copy link
Copy Markdown
Contributor

Mantis Telegram Desktop Proof

Summary: Mantis captured Telegram Desktop approval prompts; this PR still shows the same Allow Always unavailable wording.

Main screenshot This PR screenshot
Baseline native Telegram Desktop screenshot Candidate native Telegram Desktop screenshot
Main This PR
Baseline native Telegram Desktop proof GIF Candidate native Telegram Desktop proof GIF

Motion-trimmed clips:

Raw QA files: https://artifacts.openclaw.ai/mantis/telegram-desktop/pr-97081/run-28258562282-1/index.json

@harjothkhara

Copy link
Copy Markdown
Contributor

I took a pass over the new Telegram Desktop proof result and would treat it as a blocking proof failure, not just missing evidence.

The branch adds allowAlwaysUnavailableReason into the gateway protocol and threads it through the approval request/rendering path (packages/gateway-protocol/src/schema/exec-approvals.ts, src/agents/bash-tools.exec-approval-request.ts, extensions/telegram/src/approval-handler.runtime.ts, extensions/telegram/src/exec-approval-forwarding.ts, ui/src/ui/views/exec-approval.ts). But the proof comment for run 28258562282 says the candidate at 4588eb88a160 still shows the same old Allow Always unavailable wording in native Telegram.

That means the transport-visible path exercised by the proof is either not receiving allowAlwaysUnavailableReason, dropping it before the Telegram renderer, or using a different approval surface than the one covered by the tests. Before merge, I would trace the exact proof path from the registered exec approval request through the Telegram approval payload and rerun the proof on the final head. Until that flips, #97081 is not the best landing candidate; #97145 is the smaller overlapping branch, but it still needs the same visible proof before maintainers pick it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui gateway Gateway runtime mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Approval prompt wrongly says effective policy requires approval every time for non-persistable redirected command

2 participants