Skip to content

fix(exec): emit structured event when stale approval followups are suppressed (fixes #98279)#98292

Closed
liuhao1024 wants to merge 2 commits into
openclaw:mainfrom
liuhao1024:fix/exec-approval-timeout-suppressed-event
Closed

fix(exec): emit structured event when stale approval followups are suppressed (fixes #98279)#98292
liuhao1024 wants to merge 2 commits into
openclaw:mainfrom
liuhao1024:fix/exec-approval-timeout-suppressed-event

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What Problem This Solves

When an exec approval times out and OpenClaw suppresses the stale follow-up, the only signal is a free-form log.info() line. Operators who consume structured diagnostic events from the gateway event stream cannot programmatically detect this condition — they have to scrape logs or miss it entirely.

Why This Change Was Made

The exec approval followup delivery path (sendExecApprovalFollowup) drops stale followups at two points when the session key was rebound by /new or /reset:

  1. Denied followups — line ~400: Dropping stale denied exec approval followup
  2. Non-denied direct fallback — line ~433: Dropping stale exec approval followup direct fallback

Both currently emit only log.info(). This change adds a structured DiagnosticExecApprovalFollowupSuppressedEvent at both points, following the existing diagnostic event schema used throughout the gateway.

User Impact

Operators can now subscribe to exec.approval-followup.suppressed events on the diagnostic event stream to detect suppressed approval followups without log scraping. The event includes approvalId, sessionKey, and reason for downstream status/inbox tooling. Existing behavior is unchanged — this is purely additive observability.

  • AI-assisted (Hermes Agent)

Evidence

  • Behavior addressed: Emit structured diagnostic event when stale exec approval followups are suppressed
  • Environment tested: macOS, Node 22.19, OpenClaw 2026.5.28 (e932160)
  • Steps run after the patch: Ran the exec approval followup test suite which exercises both stale-followup suppression paths (denied rebound and non-denied rebound) and verifies the diagnostic event is emitted
  • Evidence after fix:
 RUN  v4.1.8 /Users/liuhao/.hermes/workdir/openclaw
 ✓  agents  src/agents/bash-tools.exec-approval-followup.test.ts (27 tests) 30ms
 Test Files  1 passed (1)
      Tests  27 passed (27)
  • Observed result after fix: All 27 tests pass including the two new assertions that verify emitInternalDiagnosticEvent is called with { type: "exec.approval-followup.suppressed", reason: "stale" } at both suppression points
  • What was not tested: Live gateway runtime with real exec approval timeout — the change is additive event emission that does not alter existing control flow

Real behavior proof

  • Behavior addressed: Emit structured diagnostic event when stale exec approval followups are suppressed
  • Environment tested: macOS, Node 22.19, OpenClaw 2026.5.28 (e932160)
  • Steps run after the patch: Ran the exec approval followup test suite which exercises both stale-followup suppression paths (denied rebound and non-denied rebound) and verifies the diagnostic event is emitted
  • Evidence after fix:
 RUN  v4.1.8 /Users/liuhao/.hermes/workdir/openclaw
 ✓  agents  src/agents/bash-tools.exec-approval-followup.test.ts (27 tests) 30ms
 Test Files  1 passed (1)
      Tests  27 passed (27)
  • Observed result after fix: All 27 tests pass including the two new assertions that verify emitInternalDiagnosticEvent is called with { type: "exec.approval-followup.suppressed", reason: "stale" } at both suppression points
  • What was not tested: Live gateway runtime with real exec approval timeout — the change is additive event emission that does not alter existing control flow

Changes Made

  • src/infra/diagnostic-events.ts: Added DiagnosticExecApprovalFollowupSuppressedEvent type with type: "exec.approval-followup.suppressed", approvalId, sessionKey, and reason fields. Added to DiagnosticEventPayload union.
  • src/agents/bash-tools.exec-approval-followup.ts: Imported emitInternalDiagnosticEvent and emit the event at both stale-followup suppression points.
  • src/agents/bash-tools.exec-approval-followup.test.ts: Added mock for emitInternalDiagnosticEvent and assertions verifying event emission in both stale-followup tests.

…ppressed

Add DiagnosticExecApprovalFollowupSuppressedEvent to the diagnostic event
system and emit it at both stale-followup suppression points in the exec
approval followup delivery path.

Fixes openclaw#98279
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: XS labels Jun 30, 2026
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 30, 2026, 9:34 PM ET / 01:34 UTC.

Summary
The PR adds an exec.approval-followup.suppressed diagnostic event from two direct stale follow-up suppression guards, updates diagnostic stability and diagnostics-otel handling, and adjusts the plugin SDK export budget.

PR surface: Source +28, Tests +17, Other 0. Total +45 across 6 files.

Reproducibility: yes. at source level: current main has both direct and gateway preflight stale follow-up suppression branches that only log or return an ok dropped summary. I did not run a live approval-timeout scenario in this read-only review.

Review metrics: 1 noteworthy metric.

  • Diagnostic event contract: 1 event type added. The event name and payload enter operator/plugin diagnostic surfaces, so maintainers should resolve coverage and vocabulary before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #98279
Summary: This PR is a candidate fix for the open structured stale approval follow-up suppression event issue, while sibling PRs target the same request with broader coverage or different event contracts.

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: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • [P1] Emit the event from the gateway preflight stale suppression branch and add focused gateway coverage.
  • Replace raw session-key stability data with bounded diagnostic fields.
  • [P1] Add redacted real behavior proof showing the event in diagnostic or stability output after rebasing.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body only shows mocked Vitest output; it needs redacted terminal/log/stability output from a real setup, and the contributor should update the PR body to trigger re-review or ask a maintainer to comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging as-is would make the linked issue appear fixed while the normal gateway preflight stale follow-up path still has no structured suppression event.
  • [P1] The new public diagnostic event name and payload would become operator/plugin contract surface while sibling PRs use different event vocabulary.
  • [P1] The stability projection currently copies a raw sessionKey into record.source, which can persist channel/target identifiers in support-bundle style output.
  • [P1] The branch is currently conflicting, so maintainers cannot evaluate it as a clean landing candidate until it is rebased or replaced.

Maintainer options:

  1. Repair this branch before merge (recommended)
    Add gateway preflight emission and coverage, replace raw session-key stability data with bounded fields, rebase the conflict, and provide redacted real behavior proof.
  2. Select a sibling contract instead
    If maintainers prefer a sibling PR's event vocabulary or coverage shape, keep the canonical issue open and close this PR only after the selected replacement is viable or merged.
  3. Accept the contract risk
    Maintainers could intentionally accept this event shape, but they would still need to own the incomplete gateway coverage and raw session-key stability exposure.

Next step before merge

  • [P1] The remaining blockers are contributor proof, branch conflict resolution, a security-sensitive payload repair, and maintainer selection of one public diagnostic event contract across competing PRs.

Security
Needs attention: The diff introduces a concrete privacy/security concern by projecting raw session keys into diagnostic stability output.

Review findings

  • [P1] Emit suppression diagnostics from the gateway preflight path — src/agents/bash-tools.exec-approval-followup.ts:398-403
  • [P1] Stop persisting raw session keys in stability snapshots — src/logging/diagnostic-stability.ts:436
Review details

Best possible solution:

Choose one stable public diagnostic contract for the canonical issue, then land a clean implementation that emits from both direct and gateway preflight suppression paths, keeps stability metadata bounded, and includes real diagnostic or stability output proof.

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

Yes, at source level: current main has both direct and gateway preflight stale follow-up suppression branches that only log or return an ok dropped summary. I did not run a live approval-timeout scenario in this read-only review.

Is this the best way to solve the issue?

No. The current PR is too narrow because it instruments only direct fallback guards, and its stability projection needs a bounded payload before the new public diagnostic contract is safe to land.

Full review comments:

  • [P1] Emit suppression diagnostics from the gateway preflight path — src/agents/bash-tools.exec-approval-followup.ts:398-403
    The added event calls only run after sendExecApprovalFollowup reaches the direct stale guards. Normal follow-ups pass execApprovalFollowupExpectedSessionId to the gateway, where the preflight rebound guard returns status: "ok" before these branches run, so the main suppression path still has no structured event.
    Confidence: 0.9
  • [P1] Stop persisting raw session keys in stability snapshots — src/logging/diagnostic-stability.ts:436
    The new stability case copies event.sessionKey into record.source, which is persisted in stability snapshots/bundles. Session keys can include channel and target identifiers such as agent:main:telegram:direct:123, while existing stability coverage intentionally strips raw sessionKey; keep this event to bounded fields like approval id, reason, and phase.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add merge-risk: 🚨 compatibility: The diff adds a public diagnostic event shape that operator and plugin tooling may rely on after merge.
  • add merge-risk: 🚨 security-boundary: The diff can preserve raw session keys in diagnostic stability output, which may expose routing identifiers beyond the intended bounded metadata.

Label justifications:

  • P2: The PR targets a focused operator-observability gap with limited runtime blast radius.
  • merge-risk: 🚨 compatibility: The diff adds a public diagnostic event shape that operator and plugin tooling may rely on after merge.
  • merge-risk: 🚨 security-boundary: The diff can preserve raw session keys in diagnostic stability output, which may expose routing identifiers beyond the intended bounded metadata.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body only shows mocked Vitest output; it needs redacted terminal/log/stability output from a real setup, and the contributor should update the PR body to trigger re-review or ask a maintainer to comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +28, Tests +17, Other 0. Total +45 across 6 files.

View PR surface stats
Area Files Added Removed Net
Source 4 28 0 +28
Tests 1 17 0 +17
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 1 1 1 0
Total 6 46 1 +45

Security concerns:

  • [medium] Raw session keys can enter stability output — src/logging/diagnostic-stability.ts:436
    record.source = event.sessionKey can persist channel/target-bearing session keys in stability snapshots or bundles; the event should use bounded, sanitized metadata instead.
    Confidence: 0.86

What I checked:

  • PR diff covers only direct stale guards: The PR adds emitInternalDiagnosticEvent calls only in sendExecApprovalFollowup direct denied and fallback stale branches, not in the gateway preflight guard used by normal follow-up requests. (src/agents/bash-tools.exec-approval-followup.ts:398, 6aee6c39128a)
  • Current gateway preflight still returns before event emission: Current main's gateway preflight stale-follow-up guard logs, writes an ok dedupe payload, responds ok, and returns before any diagnostic event is emitted. (src/gateway/server-methods/agent.ts:1495, 35af831fd0bc)
  • Existing test covers the missed path: The gateway test already exercises stale exec approval follow-up preflight suppression and currently asserts only the ok dropped summary and dedupe behavior. (src/gateway/server-methods/agent.test.ts:3193, 35af831fd0bc)
  • Public diagnostics do not expose log records: onDiagnosticEvent filters out log.record, so the existing free-form suppression log is not the public structured event stream requested by the linked issue. (src/infra/diagnostic-events.ts:1304, 35af831fd0bc)
  • Stability snapshots normally avoid raw session keys: Current stability tests assert diagnostic stability events do not preserve sessionKey; this PR maps the new event's session key into record.source. (src/logging/diagnostic-stability.test.ts:214, 35af831fd0bc)
  • Live PR state: GitHub reports this PR open at head 6aee6c39128a89fda89beeff0b2e67bc511f8560 with mergeable: CONFLICTING and mergeStateStatus: DIRTY. (6aee6c39128a)

Likely related people:

  • openperf: Authored the merged stale exec approval follow-up suppression change that added the direct and gateway preflight drop behavior now being instrumented. (role: introduced behavior; confidence: high; commits: f021633bf316; files: src/agents/bash-tools.exec-approval-followup.ts, src/gateway/server-methods/agent.ts, src/agents/bash-tools.exec-approval-followup.test.ts)
  • shakkernerd: Merged the PR that introduced the stale follow-up suppression behavior, making them a useful routing candidate for historical context. (role: merger of introduced behavior; confidence: medium; commits: f021633bf316; files: src/agents/bash-tools.exec-approval-followup.ts, src/gateway/server-methods/agent.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. P2 Normal backlog priority with limited blast radius. labels Jun 30, 2026
@openclaw-barnacle openclaw-barnacle Bot added extensions: diagnostics-otel Extension: diagnostics-otel scripts Repository scripts labels Jul 1, 2026
@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 1, 2026
@steipete

steipete commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Thanks for tackling #98279. Closing this as superseded by #98293, landed as 9f98b6e.

The landed implementation covers both suppression owners: the direct-delivery stale guard and the gateway preflight stale guard. It also keeps the diagnostic payload privacy-safe by retaining the internally generated approval ID without recording the raw session key. The selected contract is exec.approval.followup_suppressed with explicit phase and reason fields, with regression coverage for both paths and exact-head CI proof.

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

Labels

agents Agent runtime and tooling extensions: diagnostics-otel Extension: diagnostics-otel merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: XS 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.

2 participants