Skip to content

fix: keep heredoc bodies out of exec summaries#99379

Merged
openclaw-clownfish[bot] merged 1 commit into
openclaw:mainfrom
ZengWen-DT:fix/99367-heredoc-exec-summary
Jul 6, 2026
Merged

fix: keep heredoc bodies out of exec summaries#99379
openclaw-clownfish[bot] merged 1 commit into
openclaw:mainfrom
ZengWen-DT:fix/99367-heredoc-exec-summary

Conversation

@ZengWen-DT

@ZengWen-DT ZengWen-DT commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Closes #99367

What Problem This Solves

Fixes an issue where users watching exec/tool progress would see heredoc body contents reported as extra command stages when the heredoc text contained shell-like separators or generated YAML/JavaScript. A single inline script could be displayed as a chain such as run python3 inline script (heredoc) -> run if -> run console.log(b) -> show <<YAML, which made generated file contents look like commands that actually ran.

Why This Change Was Made

The exec display summarizer now removes heredoc bodies before top-level stage splitting while keeping the heredoc launcher and any real command stages that appear after the heredoc terminator. The parser reuses the existing top-level shell scanner and applies shell quote removal to heredoc delimiter words so quoted and backslash-quoted delimiters do not hide later commands.

User Impact

Operators get quieter and more accurate tool-progress summaries for inline scripts and file-generation commands. Heredoc body text no longer appears as executed shell stages, while real commands after the heredoc terminator remain visible.

Evidence

Before the fix, the current display path summarized heredoc body fragments as commands:

run python3 inline script (heredoc) -> run if -> run console.log(b) -> show <<YAML (agent)

After the fix, the same display path omits body-only fragments and still preserves a real post-heredoc command:

run python3 inline script (heredoc) -> run tests (agent)

Real exec-summary path proof from a local terminal, using the same resolveToolDisplay + formatToolDetail path that channel progress uses through src/channels/streaming.ts:

node --import tsx --input-type=module <<'EOF'
import { formatToolDetail, resolveToolDisplay } from "./src/agents/tool-display.ts";

const command = [
  "python3 <<'PY'",
  "const slugify = () => 'court-mix';",
  "if (true) console.log('a') && console.log('b');",
  "cat <<YAML",
  "- uses: subosito/flutter-action@v2",
  "YAML",
  "PY",
  "npm test",
].join("\n");

console.log(
  formatToolDetail(
    resolveToolDisplay({
      name: "exec",
      args: { command, workdir: "repo" },
      detailMode: "explain",
    }),
  ),
);
EOF

Output:

run python3 inline script (heredoc) → run tests (in repo)

The heredoc body intentionally includes &&, a nested cat <<YAML, and generated YAML-like content. Those body fragments no longer appear as command stages, while the real npm test after the PY terminator remains visible.

Actual channel progress draft proof, using the exported progress-line path from src/channels/streaming.ts:

node --import tsx --input-type=module <<'EOF'
import { formatChannelProgressDraftLineForEntry } from "./src/channels/streaming.ts";

const command = [
  "python3 <<'PY'",
  "const slugify = () => 'court-mix';",
  "if (true) console.log('a') && console.log('b');",
  "cat <<YAML",
  "- uses: subosito/flutter-action@v2",
  "YAML",
  "PY",
  "npm test",
].join("\n");

const entry = { streaming: { mode: "progress", progress: { commandText: "summary" } } };
const line = formatChannelProgressDraftLineForEntry(entry, {
  event: "tool",
  name: "exec",
  args: { command, workdir: "repo" },
  phase: "start",
});
console.log(line);
EOF

Output:

🛠️ run python3 inline script (heredoc) → run tests (in repo)

Focused validation:

node scripts/run-vitest.mjs src/agents/tool-display.test.ts
[test] passed 1 Vitest shard

node scripts/run-vitest.mjs src/agents/embedded-agent-runner/run/payloads.errors.test.ts
[test] passed 1 Vitest shard

node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo
passed

node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test.tsbuildinfo
passed

node_modules/.bin/oxfmt --check --threads=1 src/agents/tool-display-exec.ts src/agents/tool-display-exec-shell.ts src/agents/tool-display.test.ts
All matched files use the correct format.

node_modules/.bin/oxlint src/agents/tool-display-exec.ts src/agents/tool-display-exec-shell.ts src/agents/tool-display.test.ts
passed

node scripts/build-all.mjs
passed

Live/local behavior proof:

node scripts/run-node.mjs agent --local --agent main --session-key agent:main:proof-99367 --model deepseek/deepseek-v4-pro --message "Reply exactly: OPENCLAW_DEEPSEEK_OK" --json --timeout 120
provider=deepseek model=deepseek-v4-pro stopReason=stop finalAssistantVisibleText=OPENCLAW_DEEPSEEK_OK

Dependency/source contract checked:

../codex/codex-rs/app-server-protocol/src/protocol/v2/item.rs
../codex/codex-rs/app-server/src/bespoke_event_handling.rs
extensions/codex/src/app-server/event-projector.ts

Codex app-server exposes raw command, cwd, and status for command execution items, and OpenClaw maps Codex declined command status separately from this display summary path, so this PR keeps the fix in OpenClaw exec display formatting.

Local autoreview:

.agents/skills/autoreview/scripts/autoreview --mode local
autoreview clean: no accepted/actionable findings reported

AI-assisted: implementation and validation were prepared with AI assistance; proof was run locally.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Jul 3, 2026
@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 2:06 AM ET / 06:06 UTC.

Summary
The PR strips heredoc bodies before exec command stage splitting, exports the existing top-level shell scanner for that helper, and adds exec-display regression tests.

PR surface: Source +111, Tests +55. Total +166 across 3 files.

Reproducibility: yes. Current main source shows heredoc bodies can reach splitTopLevelStages(cleaned) before any heredoc-aware compaction, so body ;, &&, or || can become displayed stages; I did not run tests because this review is read-only.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #99367
Summary: This PR is the candidate fix for the canonical heredoc exec-summary display bug; the literal-newline heredoc/write report is adjacent but distinct.

Members:

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

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

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

Mantis proof suggestion
A short Slack smoke would directly exercise the visible channel-progress symptom reported by the linked issue, although it is not required for contributor proof here. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis slack desktop smoke: verify a heredoc exec progress line hides body fragments and still shows a post-terminator command.

Next step before merge

  • No repair job is needed; the PR already contains the focused fix and should proceed through normal maintainer review and merge gates.

Security
Cleared: Cleared: the diff only changes local display summarization helpers and tests, with no dependency, workflow, secret, package-resolution, or execution-surface change.

Review details

Best possible solution:

Land this focused display-parser fix after normal required merge gates stay green so the linked heredoc summary bug closes through the PR.

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

Yes. Current main source shows heredoc bodies can reach splitTopLevelStages(cleaned) before any heredoc-aware compaction, so body ;, &&, or || can become displayed stages; I did not run tests because this review is read-only.

Is this the best way to solve the issue?

Yes. The best fix is in the shared exec display summarizer before stage splitting, while channel rendering and Codex command/status mapping continue using their existing contracts.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: The PR fixes a normal-priority operator-facing exec summary bug with limited blast radius and no data-loss, security, or availability signal.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): Sufficient terminal proof in the PR body shows the after-fix exec summary and channel progress path hiding heredoc body fragments while preserving a post-terminator command.
  • proof: sufficient: Contributor real behavior proof is sufficient. Sufficient terminal proof in the PR body shows the after-fix exec summary and channel progress path hiding heredoc body fragments while preserving a post-terminator command.
Evidence reviewed

PR surface:

Source +111, Tests +55. Total +166 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 2 113 2 +111
Tests 1 55 0 +55
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 168 2 +166

What I checked:

Likely related people:

  • Lukavyi: The merged compound-command summary work replaced first-stage-only exec summaries with all-stage splitting, which made heredoc body separators visible as displayed stages. (role: introduced related behavior; confidence: medium; commits: ea67c93a123f, 0e068194aded; files: src/agents/tool-display-common.ts, src/agents/tool-display.test.ts)
  • steipete: Git history shows Peter Steinberger merged the original intent-first tool display PR and later split the exec parser into the current files. (role: feature-history owner; confidence: high; commits: ca0159569954, 2b5d8ac95120; files: src/agents/tool-display-exec.ts, src/agents/tool-display-exec-shell.ts, src/agents/tool-display-common.ts)
  • xdLawless2: The original intent-first details and deterministic exec summaries landed through this PR author before later refactors moved the code. (role: introduced display feature; confidence: medium; commits: 973c7e7b25ef, 24f213e7edd4; files: src/agents/tool-display-common.ts, src/agents/tool-display.test.ts)
  • obviyus: PR metadata shows obviyus merged the compound-command summary work and contributed adjacent cwd/preamble behavior in the same area. (role: merger and adjacent contributor; confidence: medium; commits: 0e068194aded, 08cb1f4140e6; files: src/agents/tool-display-common.ts, src/agents/tool-display.test.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: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. 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 Jul 3, 2026
@ZengWen-DT

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated the Evidence section with exact redacted terminal command output for the exec-summary display path. It shows heredoc body fragments no longer render as command stages and a real post-terminator npm test stage remains visible.

@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 3, 2026
@openclaw-clownfish
openclaw-clownfish Bot merged commit 7e81f15 into openclaw:main Jul 6, 2026
172 of 186 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: heredoc exec summaries parse body contents as command stages

1 participant