Skip to content

fix(cli): keep nodes json stdout clean#84423

Merged
giodl73-repo merged 1 commit into
openclaw:mainfrom
giodl73-repo:fix-nodes-json-stdout
May 22, 2026
Merged

fix(cli): keep nodes json stdout clean#84423
giodl73-repo merged 1 commit into
openclaw:mainfrom
giodl73-repo:fix-nodes-json-stdout

Conversation

@giodl73-repo
Copy link
Copy Markdown
Contributor

@giodl73-repo giodl73-repo commented May 20, 2026

Summary

  • route plugin-registration console logs to stderr while JSON output is being prepared
  • pass the original argv into the lazy nodes CLI registrar so openclaw nodes ... --json gets the same protection as other lazy plugin commands
  • add focused coverage for JSON flag detection and lazy subcommand argv forwarding

Verification

  • git diff --check origin/main...HEAD
  • pnpm exec oxfmt --check --threads=1 src/cli/json-output-mode.test.ts src/cli/nodes-cli/register.ts src/cli/program/register.subclis-core.ts src/cli/program/register.subclis.test.ts
  • OPENCLAW_VITEST_MAX_WORKERS=1 node scripts/run-vitest.mjs src/cli/json-output-mode.test.ts src/cli/program/register.subclis.test.ts --reporter=verbose (21 tests passed)
  • pnpm deadcode:dependencies
  • pnpm deadcode:unused-files
  • pnpm deadcode:report:ci:ts-unused
  • .agents/skills/autoreview/scripts/autoreview --mode branch (clean: no accepted/actionable findings)
  • Testbox-through-Crabbox tbx_01ks1q2yrpg4xxytr9sjfeq3xt: CI=1 NODE_OPTIONS=--max-old-space-size=4096 OPENCLAW_TEST_PROJECTS_PARALLEL=6 OPENCLAW_VITEST_MAX_WORKERS=1 OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=900000 OPENCLAW_TESTBOX=1 OPENCLAW_TESTBOX_REMOTE_RUN=1 node scripts/run-vitest.mjs src/cli/json-output-mode.test.ts src/cli/program/register.subclis.test.ts src/cli/run-main.exit.test.ts (99 tests passed)
  • WSL maintainer CLI proof: OPENCLAW_GATEWAY_TOKEN=<redacted> OPENCLAW_SKIP_CHANNELS=1 node scripts/run-node.mjs --dev gateway --reset then node scripts/run-node.mjs --dev nodes list --json > nodes-list.stdout.json 2> nodes-list.stderr.txt; command exit 0 and JSON.parse(nodes-list.stdout.json) succeeded (stdoutBytes=36, keys pending, paired).
  • Testbox-through-Crabbox tbx_01ks1qfdc3nxmaw1fdabba4n5x: CI=1 NODE_OPTIONS=--max-old-space-size=4096 OPENCLAW_TEST_PROJECTS_PARALLEL=6 OPENCLAW_VITEST_MAX_WORKERS=1 OPENCLAW_TESTBOX=1 OPENCLAW_TESTBOX_REMOTE_RUN=1 node scripts/run-vitest.mjs run --config test/vitest/vitest.e2e.config.ts src/cli/program.nodes-basic.e2e.test.ts test/cli-json-stdout.e2e.test.ts (12 tests passed)

Refs #84293

Real behavior proof

Behavior addressed: openclaw nodes list --json no longer lets lazy plugin registration logs write to stdout before JSON output.
Real environment tested: Blacksmith Testbox through Crabbox plus WSL-native maintainer worktree after rebase onto current origin/main.
Exact steps or command run after this patch: OPENCLAW_GATEWAY_TOKEN=<redacted> OPENCLAW_SKIP_CHANNELS=1 node scripts/run-node.mjs --dev gateway --reset in a temp OPENCLAW_HOME, then node scripts/run-node.mjs --dev nodes list --json > nodes-list.stdout.json 2> nodes-list.stderr.txt, followed by JSON.parse(nodes-list.stdout.json); also ran the focused unit/e2e/Testbox/deadcode proof listed above.
Evidence after fix: the real CLI run exited 0; stdout was exactly parseable JSON (stdoutBytes=36, top-level object keys pending, paired); stderr contained gateway connection/pairing diagnostics and gateway/plugin startup logs stayed outside stdout. Local focused CLI tests passed 21 tests; the exact previously failing deadcode unused-file shard passed after rebasing onto current origin/main; Testbox tbx_01ks1q2yrpg4xxytr9sjfeq3xt passed 99 tests; Testbox tbx_01ks1qfdc3nxmaw1fdabba4n5x passed 12 e2e tests.
Observed result after fix: nodes-list.stdout.json contained only { "pending": [], "paired": [] } and parsed successfully; the non-JSON gateway message scope upgrade pending approval appeared on stderr, not stdout. JSON-mode registration temporarily forces console logs to stderr, restores prior logging state afterward, and nodes lazy registration receives argv for --json detection.
What was not tested: a live LCM plugin install inside the original reporter's agent container was not exercised; the regression is covered through the CLI registration path and existing nodes/json stdout e2e suites.

@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes size: S maintainer Maintainer-authored PR labels May 20, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 20, 2026

Codex review: needs maintainer review before merge.

Workflow note: Future ClawSweeper reviews update this same comment in place.

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.

Summary
The PR forwards captured argv into lazy nodes CLI registration, uses it for JSON-mode stderr routing, and adds focused JSON flag and subcommand forwarding tests.

Reproducibility: no. live current-main reproduction was run in this read-only review. Source inspection shows the remaining gap: current main carries argv through subcommand registration, but the imported nodes registrar still reads ambient process.argv.

PR rating
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Summary: Strong focused PR with real CLI proof, Testbox validation, and no blocking findings.

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.

Real behavior proof
Sufficient (terminal): The PR body includes redacted after-fix terminal proof showing nodes list --json exits 0, stdout parses as JSON, and diagnostics stay off stdout.

Next step before merge
No automated repair is needed; the remaining action is explicit maintainer review and merge decision for a protected-label PR with sufficient proof.

Security
Cleared: Cleared: the diff is limited to CLI TypeScript and tests, with no dependency, workflow, credential, permission, or package-resolution changes.

Review details

Best possible solution:

Land the focused argv-forwarding follow-up after maintainer review, preserving the existing JSON stderr helper and focused regression coverage.

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

No live current-main reproduction was run in this read-only review. Source inspection shows the remaining gap: current main carries argv through subcommand registration, but the imported nodes registrar still reads ambient process.argv.

Is this the best way to solve the issue?

Yes. Passing captured argv into registerNodesCli is the narrow maintainable repair because it aligns nodes with the lazy subcommand registration contract while preserving the direct-call default.

Label justifications:

  • P2: This is a normal-priority CLI JSON stdout correctness follow-up with limited blast radius and focused proof.
  • rating: 🦞 diamond lobster: Current PR rating is 🦞 diamond lobster because proof is 🦞 diamond lobster, patch quality is 🦞 diamond lobster, and Strong focused PR with real CLI proof, Testbox validation, and no blocking findings.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes redacted after-fix terminal proof showing nodes list --json exits 0, stdout parses as JSON, and diagnostics stay off stdout.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted after-fix terminal proof showing nodes list --json exits 0, stdout parses as JSON, and diagnostics stay off stdout.

What I checked:

Likely related people:

  • steipete: Recent history shows work on both nodes CLI behavior and lightweight subcommand registration. (role: recent CLI and nodes contributor; confidence: medium; commits: 7fb2a356e8f2, 9bdc183b7d05; files: src/cli/nodes-cli/register.ts, src/cli/program/register.subclis-core.ts)
  • vincentkoc: Recent history shows work on the plugin parent/subcommand registration surface adjacent to the argv forwarding path. (role: adjacent CLI registration contributor; confidence: medium; commits: 2ab08c8a197e; files: src/cli/program/register.subclis-core.ts)
  • Takhoffman: The merged prior fix commit records approval and co-author routing from Takhoffman for the JSON-mode plugin registration change this PR refines. (role: reviewer for prior JSON stdout fix; confidence: medium; commits: b3ec4f08d141; files: src/cli/json-output-mode.ts, src/cli/nodes-cli/register.ts, src/cli/run-main.ts)
  • TurboTheTurtle: The replacement PR for the linked JSON stdout fix preserved source co-author credit to TurboTheTurtle, making them relevant to this exact behavior path. (role: prior fix contributor; confidence: medium; commits: b3ec4f08d141; files: src/cli/json-output-mode.ts, src/cli/nodes-cli/register.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 1f9ebb9dda36.

@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 May 20, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 20, 2026

ClawSweeper PR egg

✨ Hatched: 🥚 common Sunspot Diff Drake

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 🥚 common.
Trait: keeps receipts.
Image traits: location workflow harbor; accessory commit compass; palette seafoam, black, and opal; mood determined; pose guarding a tiny green check; shell translucent glimmer shell; lighting clean product lighting; background subtle branch markers.
Share on X: post this hatch
Copy: My PR egg hatched a 🥚 common Sunspot Diff Drake in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@giodl73-repo giodl73-repo force-pushed the fix-nodes-json-stdout branch 3 times, most recently from 77758d2 to a935d7d Compare May 21, 2026 18:40
@giodl73-repo
Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 21, 2026

🦞🧹
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.

Re-review progress:

@giodl73-repo
Copy link
Copy Markdown
Contributor Author

Rebased this onto current main and resolved the CLI JSON-output conflict by keeping the current helper name while preserving the nodes argv forwarding behavior.

Verification after rebase:

  • git diff --check origin/main...HEAD
  • ./node_modules/.bin/oxfmt --check src/cli/json-output-mode.ts src/cli/json-output-mode.test.ts src/cli/nodes-cli/register.ts src/cli/run-main.ts src/cli/program/register.subclis-core.ts src/cli/program/register.subclis.test.ts
  • OPENCLAW_VITEST_MAX_WORKERS=1 OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=.artifacts/vitest-cache/pr-84423-cli node scripts/run-vitest.mjs src/cli/json-output-mode.test.ts src/cli/program/register.subclis.test.ts src/cli/run-main.exit.test.ts --reporter=verbose (104 passed)
  • codex --dangerously-bypass-approvals-and-sandbox --sandbox danger-full-access review --commit HEAD (no actionable regressions)

Current head is signed: a935d7d77103909c1203671cdbf328c3b7994f31.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary 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 May 21, 2026
@giodl73-repo
Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Current PR head has green Real behavior proof and check-guards, and the existing durable report body says there are no concrete contributor-facing blockers. Please refresh the durable verdict so the headline/labels match the current ready state.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. 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. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 21, 2026
@giodl73-repo giodl73-repo force-pushed the fix-nodes-json-stdout branch from a935d7d to 59cb1d6 Compare May 21, 2026 23:44
@giodl73-repo
Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current origin/main, which includes the QA fixture knip ignore rename that fixes the failing check-dependencies unused-file report. Re-ran the focused CLI tests, oxfmt, git diff check, the full dependency deadcode shard pieces, and autoreview clean.

@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 21, 2026

🦞🧹
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.

Re-review progress:

@giodl73-repo
Copy link
Copy Markdown
Contributor Author

Added maintainer CLI proof to the PR body.

Real proof summary:

  • started a temp WSL dev gateway with OPENCLAW_GATEWAY_TOKEN=<redacted> and OPENCLAW_SKIP_CHANNELS=1
  • ran node scripts/run-node.mjs --dev nodes list --json > nodes-list.stdout.json 2> nodes-list.stderr.txt
  • command exited 0
  • JSON.parse(nodes-list.stdout.json) succeeded
  • stdout contained only:
{
  "pending": [],
  "paired": []
}

The gateway/plugin startup logs and the scope-upgrade diagnostic were on stderr/gateway logs, not stdout.

@clawsweeper re-review

@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 May 22, 2026
@giodl73-repo giodl73-repo merged commit ee9813f into openclaw:main May 22, 2026
195 of 200 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes maintainer Maintainer-authored PR 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.

1 participant