Skip to content

feat: implement deterministic exit codes and structured machine outpu…#173

Open
KhushviB wants to merge 28 commits into
Azure:mainfrom
KhushviB:feature/a1-deterministic-output
Open

feat: implement deterministic exit codes and structured machine outpu…#173
KhushviB wants to merge 28 commits into
Azure:mainfrom
KhushviB:feature/a1-deterministic-output

Conversation

@KhushviB

@KhushviB KhushviB commented Jul 11, 2026

Copy link
Copy Markdown

Description (#155 )

This PR implements the deterministic machine output contract (Wave 1, P0) required for the Agentic & Automation Roadmap. It ensures that the Cosmos DB Shell can be safely consumed by downstream CI/CD pipelines, automation tools, and agentic wrappers without output corruption or ambiguous failure states.

Key Changes

  • Global --output and --quiet Flags:
    • Added support for --output json, ndjson, table, and csv.
    • Added a --quiet (-q) flag that suppresses all standard informational output (banners, connection logs, etc.).
  • Deterministic Exit Codes:
    • 0: Success
    • 1: Generic error
    • 2: Bad arguments / Parser errors
    • 3: Auth / Connection failure
    • 4: Not found
    • 5: Throttled / RU budget exceeded
  • Machine Mode Protections:
    • When --output json|ndjson or --quiet are detected, the shell now implicitly disables ANSI color code injections (ColorSystem = NoColors) to prevent STDOUT corruption.
    • When --output json|ndjson is specified, it inherently behaves as --quiet to guarantee that no interactive text logs interleave with the JSON objects.
  • Structured Error Handling on stderr:
    • Any errors thrown during initialization (connection failures) or shell execution are gracefully mapped to their appropriate ExitCode and emitted as a structured JSON object ({"status": "error", "error": "..."}) to STDERR when in machine modes.

Validation / Acceptance Criteria Met

  • -c and -f runs produce parseable NDJSON implicitly.
  • No ANSI characters are rendered in machine modes.
  • Documented and stable exit codes correctly propagate to %ERRORLEVEL% / $LASTEXITCODE.
  • Tested parser error interception (returns Exit Code 2).
  • Tested early startup connection failure (returns Exit Code 1 / 3, formats to JSON).

…t (A1)

- Add --output json/ndjson/table and --quiet flags
- Implement deterministic exit codes (0: success, 1: generic, 2: bad args, 3: auth, 4: not found, 5: throttled)
- Emit structured JSON errors on stderr during machine modes
- Automatically disable ANSI colors and suppress informational output in machine modes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements a first-cut “machine output contract” for the Cosmos DB Shell by introducing global --output/--quiet flags, adding NDJSON output support, and mapping error conditions to deterministic exit codes intended for CI/CD and automation consumption.

Changes:

  • Adds root CLI flags --output/-o and --quiet/-q, and forces NoColors + quiet behavior for machine modes.
  • Introduces OutputFormat.Ndjson plus NDJSON formatting support for JSON-like command results.
  • Adds exit-code plumbing via CommandState.ExitCode, ParserErrorCommandState.ExitCode = 2, and ErrorCommandState.ExitCode mapping for Cosmos SDK failures and argument errors.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
CosmosDBShell/Program.cs Adds root options, machine-mode detection, defaulting to NDJSON in non-interactive runs, and maps parse/connect failures to deterministic exit codes.
CosmosDBShell/lang/en.ftl Adds help strings for --output and --quiet.
CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Implements Quiet suppression for ShellInterpreter.Write* and emits structured JSON errors to stderr in machine modes.
CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ParserErrorCommandState.cs Sets parser-error command states to exit code 2.
CosmosDBShell/Azure.Data.Cosmos.Shell.Core/OutputFormat.cs Adds Ndjson output format enum value.
CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ErrorCommandState.cs Adds exit-code mapping based on exception type / Cosmos status codes.
CosmosDBShell/Azure.Data.Cosmos.Shell.Core/CommandState.cs Adds ExitCode and NDJSON formatting logic; extends SetFormat to accept ndjson.
Comments suppressed due to low confidence (1)

CosmosDBShell/Azure.Data.Cosmos.Shell.Core/CommandState.cs:70

  • For an invalid format string, SetFormat currently throws ShellException, which maps to exit code 1 via ErrorCommandState. Since an invalid --output value is a bad-arguments case, throwing an ArgumentException here will allow it to deterministically map to exit code 2.
        {
            throw new ShellException(MessageService.GetString("error-invalid_output_format", new Dictionary<string, object> { { "format", outputFormat } }));
        }

Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/CommandState.cs
Comment thread CosmosDBShell/Program.cs
- Handle root System.CommandLine parser errors via JSON serialization to STDERR in machine modes
- Propagate COSMOSDB_SHELL_FORMAT automatically to command formatters
- Ignore case on JSON/NDJSON format checks
- Bypass interactive RBAC prompts in quiet/machine modes
- Prevent trailing blank lines in JSON serialization output
- Add integration tests for deterministic machine exit codes
- Update CLI argument tables in README
Copilot AI review requested due to automatic review settings July 11, 2026 18:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ErrorCommandState.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell.Tests/Integration/ShellProcessTests.cs
@mkrueger

Copy link
Copy Markdown
Collaborator

Can you fix/comment/close the copilot issues - otherwise we can't merge.

Copilot AI review requested due to automatic review settings July 13, 2026 14:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Comment thread CosmosDBShell/Program.cs Outdated
Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/CommandState.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 13, 2026 14:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ErrorCommandState.cs
Comment thread CosmosDBShell.Tests/Integration/ShellProcessTests.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 13, 2026 14:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell.Tests/Integration/ShellProcessTests.cs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 13, 2026 14:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

CosmosDBShell/Program.cs:165

  • When --output json|ndjson or --quiet is used, this early --otel validation error still writes plain text to STDOUT (and ShellInterpreter.WriteLine can't honor o.Quiet yet because ShellInterpreter.Instance.Options is assigned later). This breaks the machine-output contract by contaminating STDOUT; emit the structured error JSON to STDERR in machine mode.
                    Environment.ExitCode = 2;
                    ShellInterpreter.WriteLine(MessageService.GetArgsString(
                        "otel-error-invalid-endpoint", "endpoint", o.OtlpEndpoint));
                    return;
                }

Comment thread CosmosDBShell/Program.cs
Copilot AI review requested due to automatic review settings July 13, 2026 15:32
@mkrueger

Copy link
Copy Markdown
Collaborator

I really appreciate all input but copilot is the endboss that needs to be defeated for PRs beeing mergeable :(.

…cation scoping

- Normalize the accepted --output token to lowercase in parseArgument so
  o.Output is always a canonical lowercase value (json, ndjson, table, csv).
  Previously the raw user-supplied casing was stored, making any plain
  equality check case-sensitive.
- Hoist connectionMode and currentLocation declarations above the isQuiet
  guard in PrintConnectionInfoAsync so they are in scope for the JSON result
  dictionary regardless of quiet mode. The previous placement caused CS0841
  build errors when isQuiet was true.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 14, 2026 18:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread CosmosDBShell.Tests/Integration/ShellProcessTests.cs
Only redirect stdin in RunShellAsync when stdinScript is provided.
This keeps no-stdin invocations from being misclassified as machine mode
via Console.IsInputRedirected and preserves expected root parser behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 14, 2026 19:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Commands/ConnectCommand.cs
Copilot AI review requested due to automatic review settings July 14, 2026 19:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread CosmosDBShell/Azure.Data.Cosmos.Shell.Core/ShellInterpreter.cs Outdated
- Gate connect RBAC guidance behind interactive mode so quiet/machine runs
  do not emit interactive stdout text.
- In ShellInterpreter.PrintState, treat OperationCanceledException like other
  machine-mode failures by emitting structured JSON to stderr instead of a
  warning on stdout.
- Reuse a shared inMachineMode condition in the catch block.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 14, 2026 19:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread CosmosDBShell/Program.cs
When --output json or --output ndjson is selected, route AnsiConsole output
through TextWriter.Null using a dedicated AnsiConsoleSettings instance.
This prevents accidental AnsiConsole writes from commands from polluting
machine-readable stdout, while command-state output still uses Console.Out.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 14, 2026 19:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Comment thread CosmosDBShell/Program.cs Outdated
- Apply startup machine-mode handling to quiet mode as well as json/ndjson.
- Route startup MCP errors through structured stderr output in machine mode
  instead of unconditional AnsiConsole stdout writes.
- Keep interactive behavior unchanged for non-machine runs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 14, 2026 19:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs
Comment thread CosmosDBShell/Program.cs
- Treat startup machine mode consistently for quiet/json/ndjson and suppress
  startup informational stdout (clear-history/theme warnings).
- Route startup machine-mode errors through structured stderr JSON and return
  exit code 2 for invalid --mcp port argument.
- In PrintState, bypass AnsiConsole markup rendering in machine mode so JSON/
  text outputs always go through Console.Out.
- Expand process integration coverage for implicit -c ndjson output, machine-
  mode clear-history behavior, and invalid --mcp port behavior.
- Clarify README machine-mode wording to avoid over-promising stdout guarantees.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 14, 2026 20:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@KhushviB

Copy link
Copy Markdown
Author

@mkrueger FInally defeated the endboss 🙌🏻

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants