Skip to content

fix: preserve JSON errors for config-local format - #985

Open
saariuslystoned wants to merge 2 commits into
openclaw:mainfrom
saariuslystoned:codex/acpx-config-local-json-errors
Open

saariuslystoned wants to merge 2 commits into
openclaw:mainfrom
saariuslystoned:codex/acpx-config-local-json-errors

Conversation

@saariuslystoned

@saariuslystoned saariuslystoned commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes: config show and config init can emit only human-readable errors despite their command-local --format json when argument parsing or initial configuration loading fails.

User Impact

Scripted callers receive the existing JSON-RPC error envelope for these failures, with the existing usage exit 2 or configuration-error exit 1. A later invalid or missing repeated format value preserves the last valid format, matching global-flag error handling. Explicit global precedence, help, successful config operations and -- boundaries retain their behavior.

Why This Change Was Made

Early error handling now recognizes the existing local format option for config show and config init. It does not introduce flags, a schema or adapter behavior. The original repair and the repeated-format follow-up are included in this branch.

Evidence

Current-head local checks and GitHub CI passed. Fresh comprehensive independent P0–P3 review of the entire exact base/head branch is scoped-clean with zero findings. Hosted ClawSweeper review remains pending before final handoff. The static reviewer assessed the supplied diff and reviewed tests without executing them; actual CLI and full-test evidence is separate below. The incremental native review covers only the follow-up and is retained separately.

Exact base: af67042fac736e8c1d0cd9dd4b8057fcee85d46d. Exact head: 884063b1897d405db269126d17f2870c49927fe7 (two commits, three changed files).

Independent proof runs the actual built dist/cli.js on Linux Node 26.13.0 with synthetic isolated HOME, cwd and PATH, closed stdin and bounded subprocess timeouts. No provider requests or credentials are used.

Owning path/control Public base Current candidate
show/init local JSON + usage error Empty stdout; exit 2 JSON USAGE envelope; exit 2
show/init local JSON + malformed initial config Empty stdout; exit 1 JSON RUNTIME envelope; exit 1
Prior valid local JSON + repeated invalid/missing format Initial repair lost JSON JSON USAGE envelope; exit 2
Failed init No config written No config written
Successful init then show Existing behavior Created artifact parses and is loaded successfully; show leaves it unchanged

Original frozen entrypoint fixture: 14/14 passed; repeated-format fixture: 24/24 passed. Twelve additional independent entrypoint cases passed, including positional controls, malformed global configuration and successful init artifact/readback. The actual last-valid-format/quiet/global-precedence/separator controls remain in those fixtures.

pnpm run check: PASS on exact head: 3,189 tests, 3,173 passed, 16 skipped, zero failed/cancelled; all 247 separate coverage cases and declared 85% coverage gates passed. Coverage measures the declared flows/runtime source set, not the whole repository. pnpm run check:docs and explicit changed-Changelog formatting/Markdown lint passed.

pnpm run mutate: PASS, mutation score 92.07% (441 killed, 38 survived, 0 timeout/errors; configured unchanged src/cli/flags.ts target, not coverage of the early-error detector).

Commands:

pnpm run build
pnpm run build:test
node --test --test-name-pattern='config command|config error formats|bootstrap|compare.*json|compare.*format' dist-test/test/cli.test.js
pnpm run check
pnpm run check:docs
pnpm exec oxfmt --check CHANGELOG.md
pnpm exec markdownlint-cli2 CHANGELOG.md
pnpm run mutate

The prior-head full check failed the wrapper-exited conformance test with initialize failed: The operation was aborted. The identical failure independently reproduces on unchanged public base (two passes, then one failure); implicated test/runner/source/lock blobs are identical. Current-head focused conformance passed all 15 cases. That historical failure is retained separately and is not represented as a passing run or an F034 fix. The native broad run also failed/incomplete and is not claimed green.

Actual built-CLI captures

These captures preserve subprocess streams and exits. Disposable paths are replaced by /FIXTURE or /CHECKOUT. Usage errors retain existing human stderr alongside JSON stdout; no strict-JSON stderr claim is made. Source inspection occurred, so this is independent source-known entrypoint validation.

Base: config show local JSON usage error

{
  "argv": [
    "--cwd",
    "/FIXTURE/good",
    "config",
    "show",
    "--format",
    "json",
    "--unknown-fixture-flag"
  ],
  "exit": 2,
  "stdout": "",
  "stderr": "error: unknown option '--unknown-fixture-flag'\n\nUsage: acpx config show [options]\n\nShow resolved config\n\nOptions:\n  --format <fmt>  Output format: text, json, quiet\n  -h, --help      display help for command\nerror: unknown option '--unknown-fixture-flag'\n",
  "init_target_exists": false
}

Candidate: same usage-error owning path

{
  "argv": [
    "config",
    "show",
    "--format",
    "json",
    "--bogus"
  ],
  "case": "usage-local",
  "exit": 2,
  "stdout": "{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32602,\"message\":\"error: unknown option '--bogus'\",\"data\":{\"acpxCode\":\"USAGE\",\"origin\":\"cli\",\"sessionId\":\"unknown\"}}}\n",
  "stderr": "error: unknown option '--bogus'\n\nUsage: acpx config show [options]\n\nShow resolved config\n\nOptions:\n  --format <fmt>  Output format: text, json, quiet\n  -h, --help      display help for command\n",
  "configUnchanged": true
}

Candidate: early malformed configuration error

{
  "argv": [
    "config",
    "show",
    "--format",
    "json"
  ],
  "case": "malformed-config-local",
  "exit": 1,
  "stdout": "{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32603,\"message\":\"Invalid JSON in /FIXTURE/home/.acpx/config.json: Expected property name or '}' in JSON at position 1 (line 1 column 2)\",\"data\":{\"acpxCode\":\"RUNTIME\",\"origin\":\"cli\",\"sessionId\":\"unknown\"}}}\n",
  "stderr": "",
  "configUnchanged": true
}

Candidate: valid JSON then missing repeated format on init

{
  "argv": [
    "config",
    "init",
    "--format",
    "json",
    "--format"
  ],
  "code": 2,
  "stdout": "{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32602,\"message\":\"error: option '--format <fmt>' argument missing\",\"data\":{\"acpxCode\":\"USAGE\",\"origin\":\"cli\",\"sessionId\":\"unknown\"}}}\n",
  "stderr": "error: option '--format <fmt>' argument missing\n\nUsage: acpx config init [options]\n\nCreate global config template\n\nOptions:\n  --format <fmt>  Output format: text, json, quiet\n  -h, --help      display help for command\n",
  "configWritten": false
}

AI-assisted contribution: RoboClaw implementation; Codex independent reproduction and validation. Maintainer edits are enabled. Human approval is required for merge; no merge is requested or performed.

RoboClaw (AI assistant) and others added 2 commits November 8, 2026 04:10
Co-authored-by: saariuslystoned <159389674+saariuslystoned@users.noreply.github.com>
Co-authored-by: saariuslystoned <159389674+saariuslystoned@users.noreply.github.com>
@clawsweeper

clawsweeper Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added the clawsweeper:intake:bug Preliminary submission classification; full source review pending. label Nov 8, 2026
@saariuslystoned
saariuslystoned marked this pull request as ready for review November 8, 2026 05:05
@saariuslystoned
saariuslystoned requested a review from a team as a code owner November 8, 2026 05:05
@clawsweeper

clawsweeper Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

What this changes

Preserve command-local JSON formatting for config show and config init errors during parsing and configuration loading.

Example: Run acpx config show --format json --bogus.

  • Before: Exit 2 with empty stdout and human-readable stderr.
  • After: Exit 2 with a JSON-RPC USAGE error on stdout.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) Useful, focused repair with actual CLI evidence, held back by one concrete argument-consumption defect.
Proof confidence 🦞 diamond lobster (5/6) Sufficient (terminal): Supplied exact-head terminal captures exercise built dist/cli.js on Linux Node 26.13.0 through the changed early-output owner, demonstrating JSON usage/configuration errors and preserved failure exits.
Patch quality 🦐 gold shrimp (3/6) 1 actionable review finding remain.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: Scripted config callers lose machine-readable errors despite selecting the existing local JSON format.
Reason: Restoring the existing output contract supports the agent-first CLI without adding public conventions.

Merge readiness

⛔ Needs changes before merge - 1 item remains

This PR fixes a current-main error-formatting gap, but its new scanner misinterprets consumed option values as format flags.

Priority: P2
Reviewed head: 884063b1897d405db269126d17f2870c49927fe7

Before merge

  • Skip consumed values when scanning config-local format flags (P2) - For acpx config show --format quiet --format --format=json, Commander consumes --format=json as the invalid value of the preceding required option. This scan instead recognizes it as an independent JSON flag and emits a JSON error on stdout, overriding the last valid quiet selection. Conversely, a consumed --format=quiet can erase a preceding valid JSON selection. Both config commands are affected. Scan forward, skip each consumed --format value, retain the last valid format, and add regression coverage for these cases.

Findings

  • [P2] Skip consumed values when scanning config-local format flags — src/cli-core.ts:282-285

Tests

  • Missing end-to-end proof: The supplied captures and added tests do not cover a format-looking token consumed as the value of a preceding --format.
Agent review details

How this fits together

The CLI selects an error-output policy from arguments before loading configuration and parsing commands, then sends failures through the shared error formatter.

flowchart TD
Arguments --> FormatDetection
FormatDetection --> OutputPolicy
Arguments --> ConfigLoading
ConfigLoading --> CommandParsing
CommandParsing --> ErrorHandler
OutputPolicy --> ErrorHandler
ErrorHandler --> OutputStreams
Loading

Technical review

Best possible solution:

Use a forward, value-aware config-local scan that preserves the last valid format and existing root precedence.

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

Current-main source explains the reported missing JSON errors, and supplied built-CLI captures demonstrate them; the consumed-value defect is source-verifiable without executing target code.

Is this the best way to solve the issue?

Extending the existing early-output owner is appropriate, but scanning must respect required-option consumption rather than treating every token as an independent flag.

Full review comments:

  • [P2] Skip consumed values when scanning config-local format flags — src/cli-core.ts:282-285
    For acpx config show --format quiet --format --format=json, Commander consumes --format=json as the invalid value of the preceding required option. This scan instead recognizes it as an independent JSON flag and emits a JSON error on stdout, overriding the last valid quiet selection. Conversely, a consumed --format=quiet can erase a preceding valid JSON selection. Both config commands are affected. Scan forward, skip each consumed --format value, retain the last valid format, and add regression coverage for these cases.
    Confidence: 0.98

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against af67042fac73.

Provenance checked

  • Compare-local early error selection keeps the original intent (8d29425: Normalize compare output before validation while preserving precedence, consumed values, and delimiters.)

Testing

Proof path: shipped entry point.

Security

None.

Evidence

Acceptance criteria:

  • pnpm run build:test
  • node --test --test-name-pattern='config command|config error formats|bootstrap|compare.*json|compare.*format' dist-test/test/cli.test.js
  • pnpm run check
  • pnpm run check:docs

What I checked:

Likely related people:

  • Peter Steinberger: Raw commit 8d29425 adds src/cli-core.ts:219 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 8d29425e77f6; files: src/cli-core.ts)
  • Vincent Koc: Raw commit 77715c8 adds src/cli-core.ts:222 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: medium; commits: 77715c8d7c18; files: src/cli-core.ts)

Preflight source

Source unknown. Source comparison at the observed PR snapshot only. Completion is self-reported; body, policy, tests, execution, and report bytes are not verified.

Review metrics

Metric Value Why it matters
Change size Production +31/-4 lines; tests +74 lines The change stays within early format detection and exercises both config commands and precedence controls.

Labels

Label changes:

  • add P2: Incorrect error formatting affects scripted config callers, with limited scope and a focused repair.
  • add proof: sufficient: Contributor real behavior proof is sufficient.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action.

Label justifications:

  • P2: Incorrect error formatting affects scripted config callers, with limited scope and a focused repair.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action.
  • proof: sufficient: Contributor real behavior proof is sufficient.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

Reviewed November 8, 2026, 12:05 AM ET / 05:05 UTC.

This branch has not been deployed

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

Labels

clawsweeper:intake:bug Preliminary submission classification; full source review pending.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant