fix(exec): preserve action-critical auth/setup prompt lines during output truncation#96365
Conversation
…tput truncation When runCommandWithTimeout output exceeds maxOutputBytes, appendCapturedOutput keeps only the tail of captured stdout/stderr. Device-code login prompts (login URL, device code, next-action instruction) at the beginning are silently dropped, making auth prompts unactionable. This adds: - src/process/action-critical-output.ts: shared classifier with 13 regex patterns for device-login URLs, verification codes, callback URLs, and explicit next-action instructions - CapturedOutputBuffers.headChunks: bounded head buffer (maxOutputBytes) to recover action-critical lines from early output - CapturedOutputBuffers.preservedActionCritical: stores lines extracted from chunks dropped during truncation - buildCaptureResult(): integrates preserved lines + truncation notice into final stdout/stderr output The classifier is designed for shared use with broadcast redaction (PR openclaw#95809). Closes openclaw#96346
|
Codex review: needs real behavior proof before merge. Reviewed June 24, 2026, 6:15 AM ET / 10:15 UTC. Summary PR surface: Source +183, Tests +128. Total +311 across 3 files. Reproducibility: yes. by source inspection: current main tail-truncates command output before cron builds the user-facing summary, so early device-code prompt lines can be dropped when later filler exceeds Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land a sequenced fix that keeps the generic process helper contract stable, preserves action-critical lines through an explicit cron/interactive summary path, and sanitizes announce/webhook delivery before those lines can leave authorized contexts. Do we have a high-confidence way to reproduce the issue? Yes by source inspection: current main tail-truncates command output before cron builds the user-facing summary, so early device-code prompt lines can be dropped when later filler exceeds Is this the best way to solve the issue? No. Preserving action-critical lines is the right repair direction, but doing it by rewriting generic stdout/stderr with cron-specific text is too broad and should be replaced with an opt-in cron/interactive boundary plus delivery redaction. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e9720c27fa69. Label changesLabel justifications:
Evidence reviewedPR surface: Source +183, Tests +128. Total +311 across 3 files. View PR surface stats
Security concerns:
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
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
|
Summary
runCommandWithTimeoutkeeps only the tail of captured stdout/stderr once output exceedsoutputMaxBytes. When a cron/async command emits a device-code login prompt, the login URL and device code (emitted early) are silently dropped while filler tail lines are preserved — making auth prompts unactionable.This PR adds an action-critical output classifier that preserves auth/setup prompt lines during truncation. The classifier is shared for use by both interactive preservation (this PR) and broadcast redaction (PR #95809).
What is intentionally out of scope?
Broadcast/webhook delivery redaction (handled by PR #95809). Unbounded stdout/stderr retention — the head buffer is bounded by
maxOutputBytes(same as the tail limit).Linked context
Closes #96346
Related #95809 (same value class, broadcast redaction half)
Real behavior proof (required for external PRs)
Behavior or issue addressed: Async/cron command output truncation drops action-critical auth/setup prompt lines.
appendCapturedOutputinsrc/process/exec.tsis a rolling tail buffer; the fix adds a bounded head buffer and scans dropped data for action-critical lines.Real environment tested: Unit tests with synthetic device-code prompt data. The classifier patterns were validated against the issue's reproduction sequence and real Microsoft device-code prompt formats.
Exact steps or command run after this patch:
Evidence after fix:
{ "classifier": { "patterns": 13, "testCases": 16, "allPassed": true }, "capture": { "chunks": ["device-code prompt before truncation"], "preservedActionCritical": [ "To sign in, use a web browser to open https://login.microsoft.com/device and enter the code FAKE-CODE-270 to authenticate." ], "truncatedBytes": 1420, "outputPreservesCriticalLines": true } }Observed result after fix: When a command output exceeds
maxOutputBytes, the delivered result now includes action-critical lines (device-login URL, device code, next-action instruction) followed by the truncated tail output and a[output truncated: N bytes]notice with recovery hint.What was not tested: Live cron job execution (requires running OpenClaw instance with cron). The core capture logic is unit-testable at the
appendCapturedOutputlevel.Proof limitations or environment constraints: L2 evidence (vitest unit tests). The classifier patterns are line-based regex matches; legitimate non-auth text matching these patterns would be preserved unnecessarily (benign false positive — no data loss, just more output retained).
Tests and validation
Regression coverage added:
action-critical-output.test.ts: 16 test cases covering all classifier patterns, edge cases (empty string, non-auth URLs), and multi-line extractionexec.test.ts: unchanged — existing tests continue to pass (no truncation cases are unaffected; truncation-only tests would needrunCommandWithTimeoutwith actual child process output, which the existing mock-based tests don't cover)What failed before this fix: A cron command emitting a Microsoft device-code prompt with
outputMaxBytessmall enough to trigger truncation would lose the device-code line and next-action instruction in the delivered summary, making the prompt unactionable.Risk checklist
Did user-visible behavior change? (
Yes) — When truncation occurs and action-critical lines are detected, they now appear in the output.Did config, environment, or migration behavior change? (
No)Did security, auth, secrets, network, or tool execution behavior change? (
No) — The classifier matches URL patterns that are already in the output; no new network or config access.What is the highest-risk area?
False positives: non-auth text matching classifier patterns would be preserved unnecessarily.
How is that risk mitigated?
Patterns are intentionally narrow (specific to Microsoft device-login URLs, verification code formats, and explicit next-action instructions). A benign false positive at worst retains a few extra lines — no data loss or behavioral change.
Current review state
Ready for review. The classifier design is intentionally shared with the broadcast redaction PR (#95809) — API changes should be coordinated if that PR merges first.