Files
distributor/docs/roadmap/cli_output_policy.md

243 lines
8.4 KiB
Markdown

# Roadmap: CLI Output Policy
## Purpose
Define a shared CLI output policy before adding machine-readable JSON output to
`distributor` commands.
Current CLI output is human-readable text. That is appropriate as the default,
but upcoming features need a common machine-readable contract so each command
does not invent a separate JSON flag, envelope, warning policy, or error shape.
## Current Implementation Grounding
The current CLI has these output-producing commands:
- `version`;
- `run`;
- `validate`;
- `inspect`.
Current output is text-only. `run` has the most complex output because it can
print warnings, pipeline summaries, planned destination actions, partial
destination failures, and a final status line. `validate` and `inspect` are
currently local-path commands. `version` prints a single text line.
Planned `distributor manifest create`, remote `validate` and `inspect`, link
generation, and latest path destinations increase the need for structured
output that scripts can consume consistently.
## Goals
- Define one CLI-wide policy for text and JSON output.
- Preserve current human-readable text output as the default.
- Add JSON output consistently across output-producing commands when this
roadmap is implemented.
- Keep warning, error, and partial-failure behavior predictable.
- Avoid external dependencies; use Go's standard `encoding/json`.
## Non-Goals
- Do not add YAML, table, NDJSON, streaming JSON, or template output formats.
- Do not change source manifest, destination state, config, or backend schemas.
- Do not make help or usage output JSON.
- Do not turn ordinary fatal setup errors into structured JSON results.
- Do not add a root-global output flag in the first implementation.
## Shared CLI Policy
Each supported command should accept:
```sh
--format text
--format json
```
Policy:
- `text` is the default and preserves existing output unless a feature
explicitly changes text output.
- `json` writes exactly one JSON document to stdout.
- help and usage output remain text-only.
- invalid `--format` values are usage errors.
- `--format` is a per-command flag, not a root-global flag.
- a command must not accept `--format json` unless it emits the shared JSON
envelope for that command.
The first implementation should add JSON support for all current
output-producing commands rather than leaving a mixed CLI where some commands
support `--format` and others do not.
## Stdout, Stderr, Warnings, and Errors
Text mode keeps the current behavior:
- normal command output goes to stdout;
- warnings may be printed as text;
- command errors are printed to stderr by CLI error handling.
JSON mode:
- successful commands write one JSON document to stdout;
- warnings are included in a top-level `warnings` array and are not duplicated
to stderr;
- fatal setup errors that prevent construction of a result write text errors to
stderr, write no JSON stdout, and exit non-zero;
- commands with meaningful partial results may write a JSON document with
`ok: false`, structured failure details, and a non-zero exit status.
`run --format json` should use the partial-result behavior when planning or
execution has begun and one or more destinations fail. This lets automation
inspect successful actions, failed actions, warnings, and final counters even
when the process exits non-zero.
## JSON Envelope
All JSON-mode commands should use a common top-level envelope:
```json
{
"schema_version": 1,
"command": "inspect",
"ok": true,
"warnings": [],
"result": {}
}
```
Envelope fields:
- `schema_version`: integer version of the CLI JSON output schema.
- `command`: command name, using the public CLI command path where useful, such
as `manifest create`.
- `ok`: boolean success indicator for the command result.
- `warnings`: array of structured warning objects.
- `result`: command-specific result object.
- `errors`: optional array of structured error objects for commands that can
return partial results.
Field rules:
- use stable snake_case field names;
- use RFC3339 timestamps;
- use numeric JSON values for sizes and counts;
- use slash-separated logical paths for bundle, source, destination, and output
paths;
- never include secret values;
- keep command-specific data under `result`;
- add fields compatibly where practical.
Warning objects should include at least:
```json
{
"message": "secret OBJECT_STORAGE_KEY ignored because the real environment already has that variable"
}
```
Error objects for partial results should include enough context for automation
and troubleshooting, such as pipeline id, destination id, backend, bundle path,
and message when those values are available.
## Command Adoption
`version`:
- text mode keeps the current version string;
- JSON mode reports application name and version under `result`.
`validate`:
- text mode keeps the current validation summary;
- JSON mode reports bundle count and selected bundle identifiers;
- future remote validation uses the same envelope and adds pipeline/source
context under `result`.
`inspect`:
- text mode keeps human-readable bundle metadata;
- JSON mode reports normalized bundle metadata, including source-relative path,
bundle id, created timestamp, digest, file count, total size, and file
records.
`run`:
- text mode keeps the current progress and final status style unless a future
feature intentionally changes it;
- JSON mode reports warnings, pipeline summaries, destination action records,
output records, final counters, dry-run status, and partial failure records;
- JSON mode may write `ok: false` with partial results and still exit non-zero.
Future `manifest create`:
- should use `--format text|json`;
- text mode should keep concise human success output;
- JSON mode should report the generated manifest summary under `result`;
- the command should not introduce a separate `--json` flag.
## Relationship To Other Roadmaps
`distributor manifest create` should depend on this roadmap for JSON summary
output and should not add a command-specific JSON flag.
Remote `validate` and `inspect` should use this policy for machine-readable
source validation and inspection.
Link generation should expose primary links through JSON command output only
after this policy is implemented or selected for implementation.
Latest path destinations should report fixed-path selection and destructive
replacement summaries through the same `run --format json` result model.
## Testing Expectations
Suggested coverage:
- CLI parsing accepts `--format text` and `--format json` for supported
commands;
- CLI parsing rejects invalid `--format` values as usage errors;
- help and usage output remain text-only;
- each JSON-capable command emits exactly one valid JSON document to stdout on
success;
- text mode preserves existing output;
- JSON-mode warnings appear in `warnings` and are not duplicated to stderr;
- fatal setup errors write no JSON stdout and return non-zero;
- `run --format json` emits partial-result JSON with `ok: false` and exits
non-zero when one or more destination failures occur after planning begins;
- JSON output uses RFC3339 timestamps, numeric sizes and counts, and
slash-separated logical paths;
- no JSON output includes secret values;
- documentation consistency checks find no unsupported `--json` references.
## Documentation Updates After Implementation
- Update `docs/cli.md` with the shared `--format text|json` policy.
- Update command examples only for implemented JSON behavior.
- Update `docs/operations.md` where JSON output materially improves automation
workflows.
- Update `docs/troubleshooting.md` only for implemented JSON-mode recovery
behavior.
- Update relevant roadmap files when JSON output is no longer deferred.
Keep this roadmap under `docs/roadmap/` until implemented.
## Decisions
- Use per-command `--format text|json`; do not introduce `--json`.
- Keep `text` as the default for backward compatibility.
- Implement JSON support for all current output-producing commands when this
roadmap is selected.
- Keep help and usage output text-only.
- Put JSON-mode warnings in the top-level `warnings` array.
- Allow `run --format json` to emit partial-result JSON with `ok: false` and a
non-zero exit status.
- Keep fatal setup errors as text stderr with no JSON stdout.
## Future Work
- Consider a root-global output flag only if the command parser is later
refactored around shared root options.
- Consider additional formats only if a concrete consumer requires them.
- Consider a versioned JSON schema reference after the first JSON-capable
release.