Skip to content

Support colored pretty JSON and structured tool result payloads #248

@coisa

Description

@coisa

Problem

--pretty-json currently preserves valid, parseable JSON by pretty-printing the same structured payload emitted by --json. Adding ANSI escape sequences directly to that output would make the stream easier for humans to scan, but it would also make the payload invalid JSON for tools that pipe, parse, or archive the command output.

At the same time, several orchestrated commands still expose subprocess output as plain text. That makes --json and --pretty-json less useful for agents, CI consumers, and future dashboards because important details from PHPUnit, Rector, ECS, PHP-CS-Fixer, PhpMetrics, phpDocumentor, and Composer-backed checks remain embedded in raw strings instead of stable structured fields.

Proposal

Evaluate and implement a non-intrusive colored pretty JSON experience while preserving the machine-readable contract of JSON modes. If color is supported, it MUST be explicitly terminal-safe and MUST NOT silently corrupt JSON consumed by automation.

In the same design, extend command result payloads so full tool executions can return structured summaries instead of only raw subprocess strings. The color work should build on those structured results rather than becoming a standalone syntax-highlighting shortcut that is hard to evolve.

Goals

  • Keep --json and the default --pretty-json output valid JSON for scripts, CI, and agents.
  • Provide a terminal-friendly way to inspect pretty JSON with color when it is safe and explicit.
  • Convert known orchestrated tool results into structured JSON summaries where the upstream tool exposes parseable data.
  • Preserve raw output as a fallback/debug field when a tool does not provide enough structured data.

Expected Behavior

Maintainers can keep using composer dev-tools ... --pretty-json as parseable JSON. If a colored mode is introduced, it is opt-in or otherwise impossible to confuse with strict JSON output. Agents and CI consumers can inspect fields such as command label, exit code, duration, artifacts, violations, changed files, coverage summaries, or generated report paths without scraping terminal output.

Implementation Strategy

Start by documenting the output contract for JSON modes and deciding whether color belongs behind a distinct option, a terminal-only renderer, or a separate command/output sink. Avoid adding ANSI escapes to strict JSON output.

Then incrementally enrich command results by mapping existing tool outputs into stable arrays. Useful candidates include:

  • PHPUnit: test count, assertions, failures, errors, skipped tests, coverage artifact paths, and exit code.
  • Rector: changed files, applied rules when available, dry-run status, and exit code.
  • ECS/PHP-CS-Fixer: violations/fixed files, formatter output, and exit code.
  • PhpMetrics: generated report paths, summary JSON location, package analysis status, and exit code.
  • phpDocumentor docs/wiki: generated target paths, warnings when available, and exit code.
  • Composer-backed checks: analyzed command, lockfile/package metadata when available, and exit code.

The implementation should reuse the current logger/process queue surfaces where possible, and only introduce new classes when a focused parser or renderer has a clear boundary.

Requirements

  • --json MUST remain compact, valid JSON without ANSI escape sequences.
  • --pretty-json MUST remain valid JSON unless a separate, explicitly documented color mode is introduced.
  • Any colored terminal rendering MUST be disabled automatically for non-decorated output, redirected streams, or agent contexts where JSON is expected to be parsed.
  • Structured subprocess summaries MUST include enough metadata to debug failures without relying solely on raw output.
  • Raw subprocess output MAY remain available, but it SHOULD NOT be the only representation for supported tools.
  • Documentation for affected commands MUST explain the strict JSON contract, any colored terminal mode, and the structured fields that are guaranteed.

Non-goals

  • Do not color strict JSON output by injecting ANSI escape sequences into --json or default --pretty-json.
  • Do not implement a full terminal UI or replace existing command logs.
  • Do not require every external tool to be parsed in one PR; this can ship incrementally per command/tool.

Benefits

This keeps JSON modes reliable for automation while making human inspection nicer and future agent workflows more precise. It also reduces brittle string scraping by giving structured consumers first-class fields for command outcomes and generated artifacts.

Acceptance Criteria

Functional Criteria

  • The strict JSON output contract is documented and covered by tests.
  • A colored pretty JSON approach is either implemented safely or explicitly deferred with the chosen reason documented.
  • --json and default --pretty-json remain parseable by json_decode() in tests.
  • At least one orchestrated tool command emits a structured summary beyond a raw output string.
  • Structured command payloads include command label, exit code, and enough tool-specific fields to avoid scraping terminal text for the supported tool.
  • Unsupported or partially supported tools retain raw output fallback without breaking the top-level schema.

Architectural / Isolation Criteria

  • Command classes remain orchestration-only; parsing/rendering logic lives in focused collaborators when it becomes non-trivial.
  • The implementation avoids new composer/composer coupling while DevTools is being decoupled from Composer internals.
  • Tests use mocks for collaborators and instantiate only the subject under test unless a literal object is unavoidable.
  • Docs and changelog entries are updated for any changed CLI behavior or output schema.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions