Skip to content

fix(cli): validate/recipe UX papercuts (#1383 items 1-7)#1391

Merged
mchmarny merged 1 commit into
mainfrom
fix/cli-ux-papercuts
Jun 16, 2026
Merged

fix(cli): validate/recipe UX papercuts (#1383 items 1-7)#1391
mchmarny merged 1 commit into
mainfrom
fix/cli-ux-papercuts

Conversation

@mchmarny

Copy link
Copy Markdown
Member

Summary

Resolves items 1–7 of the #1383 tracker — the remaining validate/recipe CLI UX papercuts split out from #1361. (The big symptom, the repeated chainsaw: no such file, was already fixed by the in-process chainsaw executor; item 8 came along with that move and is left to confirm/close separately.)

Motivation / Context

These are small, independent, same-area UX fixes that make the CLI legible to a confused user. Bundled per the tracker's own framing ("fixable in one or two PRs").

Fixes: #1383

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Component(s) Affected

  • CLI (cmd/aicr, pkg/cli)
  • Collectors / snapshotter (pkg/collector, pkg/snapshotter)
  • Core libraries (pkg/errors, pkg/k8s) — pkg/logging, pkg/serializer

Implementation Notes

  1. Failed validator now red, not green. pkg/logging/cli.go colored strictly by log level, so a slog.Info("validator completed", "status", "failed") rendered green. The handler now also reds a record carrying status=failed/error (hasFailureStatus). No log-level reclassification, so AICR_LOG_LEVEL filtering is untouched.
  2. recipe lists component names, not just the count, on the completion line.
  3. Mode banners. recipe logs that it runs offline (reads inputs, never deploys/modifies a cluster); validate distinguishes live-cluster vs --no-cluster dry-run.
  4. -o table nested rendering. The table flattener now renders maps, scalar slices, and multi-line strings as single-line compact JSON (struct and struct-slice recursion preserved), so nested values.yaml fragments no longer shatter the FIELD/VALUE columns. Empty top-level collections still print <empty>.
  5. any legend. recipe list table output appends a one-line legend that any = wildcard/unconstrained. Human-readable surface only — the recipe YAML/JSON body still emits the literal any.
  6. Agent readiness warning now names namespace and jobName.
  7. GPU-scheduling hint shows concrete, repeatable --node-selector key=value syntax.

Testing

make test   # pass, total coverage 77.2% (>= 70% floor)
golangci-lint run -c .golangci.yaml ./pkg/logging/... ./pkg/serializer/... ./pkg/cli/... ./pkg/snapshotter/...   # 0 issues

New tests: status-attr coloring (failed/error→red, passed/skipped→green); table compact-JSON leaves (nested map, scalar slice, multi-line string) + empty-data still <empty>; recipe list wildcard legend.

Risk Assessment

  • Low — UX/output changes only; no control-flow changes. The only behavior change with test surface is -o table nested rendering, covered by new + existing tests.

Rollout notes: -o table now collapses nested values into compact JSON cells instead of exploding/garbling them — more readable, but anyone scraping the old per-key table rows should use -o json/-o yaml (the machine-readable formats, unchanged).

Checklist

  • Tests pass locally (make test with -race)
  • Linter passes (make lint)
  • I did not skip/disable tests to make CI green
  • I added/updated tests for new functionality
  • I updated docs if user-facing behavior changed
  • Changes follow existing patterns in the codebase
  • Commits are cryptographically signed (git commit -S)

@mchmarny mchmarny requested a review from a team as a code owner June 16, 2026 17:24
@mchmarny mchmarny added the theme/validation Constraint evaluation, health checks, and conformance evidence label Jun 16, 2026
@mchmarny mchmarny self-assigned this Jun 16, 2026
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 9a2d55f4-cbdf-4c58-9419-de76c5750061

📥 Commits

Reviewing files that changed from the base of the PR and between 4976133 and d6b824d.

📒 Files selected for processing (9)
  • pkg/cli/recipe.go
  • pkg/cli/recipe_list.go
  • pkg/cli/recipe_list_test.go
  • pkg/cli/validate.go
  • pkg/logging/cli.go
  • pkg/logging/cli_test.go
  • pkg/serializer/writer.go
  • pkg/serializer/writer_test.go
  • pkg/snapshotter/agent.go

📝 Walkthrough

Walkthrough

This PR delivers several CLI output quality improvements. pkg/logging/cli.go gains a hasFailureStatus helper that causes INFO-level log records with a status of failed or error to be colored red, matching error-level behavior. pkg/serializer/writer.go rewrites flattenValue to collapse map and scalar-slice values into compact JSON cells instead of exploding them into rows, and adds three private helpers. pkg/cli/recipe.go adds an offline-mode banner and appends component names to the completion log. pkg/cli/validate.go adds a mode banner distinguishing --no-cluster from live-cluster runs. pkg/cli/recipe_list.go prints a wildcard legend for criteriaAny in table output. pkg/snapshotter/agent.go enriches two diagnostic messages with job name and expanded GPU node-selector guidance.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested labels

area/docs

Suggested reviewers

  • lalitadithya
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(cli): validate/recipe UX papercuts (#1383 items 1-7)' clearly and specifically identifies the main change as a set of UX fixes for validate/recipe commands addressing specific issues from tracker #1383.
Description check ✅ Passed The PR description provides detailed context explaining items 1–7 of the #1383 tracker, motivation, implementation notes, testing results, and risk assessment—all directly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cli-ux-papercuts

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/logging/cli_test.go`:
- Around line 96-127: Add a test case to the
TestCLIHandler_FailureStatusColoredRed function that validates handler-bound
status attributes. Create a test variant that uses logger.With("status",
"...").Info(...) to log a record, ensuring the colorization logic that checks
h.attrs (handler-bound attributes) is covered. This should verify that status
values set via logger.With() are correctly colored red or green just like status
values passed directly to logger.Info().

In `@pkg/snapshotter/agent.go`:
- Around line 209-210: The bare string values being passed to slog.Warn() at
lines 209-210 for the "namespace" and "jobName" fields do not follow the
established logging pattern used elsewhere in this file. Wrap both string field
values with the slog.String() helper function to match the consistent structured
logging pattern used at lines 161, 168, and 182. This ensures all string fields
are properly wrapped with their respective type helpers when passed to
slog.Warn().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 23100763-1a37-4218-862e-587dd211bebf

📥 Commits

Reviewing files that changed from the base of the PR and between 732a8dd and 57012ca.

📒 Files selected for processing (9)
  • pkg/cli/recipe.go
  • pkg/cli/recipe_list.go
  • pkg/cli/recipe_list_test.go
  • pkg/cli/validate.go
  • pkg/logging/cli.go
  • pkg/logging/cli_test.go
  • pkg/serializer/writer.go
  • pkg/serializer/writer_test.go
  • pkg/snapshotter/agent.go

Comment thread pkg/logging/cli_test.go
Comment thread pkg/snapshotter/agent.go Outdated
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Coverage Report ✅

Metric Value
Coverage 77.2%
Threshold 75%
Status Pass
Coverage Badge
![Coverage](https://img.shields.io/badge/coverage-77.2%25-green)

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/NVIDIA/aicr/pkg/cli 69.06% (+0.05%) 👍
github.com/NVIDIA/aicr/pkg/logging 97.67% (+1.90%) 👍
github.com/NVIDIA/aicr/pkg/serializer 72.40% (+0.07%) 👍
github.com/NVIDIA/aicr/pkg/snapshotter 49.84% (ø)

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/NVIDIA/aicr/pkg/cli/recipe.go 84.30% (+0.54%) 121 (+4) 102 (+4) 19 👍
github.com/NVIDIA/aicr/pkg/cli/recipe_list.go 77.59% (-0.48%) 116 (+2) 90 (+1) 26 (+1) 👎
github.com/NVIDIA/aicr/pkg/cli/validate.go 35.75% (+0.53%) 179 (+3) 64 (+2) 115 (+1) 👍
github.com/NVIDIA/aicr/pkg/logging/cli.go 97.14% (+2.60%) 70 (+15) 68 (+16) 2 (-1) 👍
github.com/NVIDIA/aicr/pkg/serializer/writer.go 89.04% (-1.73%) 146 (+16) 130 (+12) 16 (+4) 👎
github.com/NVIDIA/aicr/pkg/snapshotter/agent.go 30.93% (ø) 194 60 134

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

@mchmarny mchmarny force-pushed the fix/cli-ux-papercuts branch from 57012ca to 4976133 Compare June 16, 2026 17:45
lalitadithya
lalitadithya previously approved these changes Jun 16, 2026
@mchmarny mchmarny enabled auto-merge (squash) June 16, 2026 17:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/serializer/writer.go`:
- Around line 285-291: The string escape check in the condition around line 287
only detects newline characters with strings.Contains(s, "\n"), but tab and
carriage return characters can also distort tabwriter alignment. Expand the
condition to also check for the presence of `\t` and `\r` characters in the
string value, so that compactJSONLeaf is called whenever any of these
problematic characters are detected, ensuring consistent table formatting
regardless of which whitespace characters are present in the string.

In `@pkg/snapshotter/agent.go`:
- Around line 208-211: The warning log in the agent.go file uses the field key
"jobName" in the slog.String call for agentConfig.JobName, but this value is
logged with the field key "job" elsewhere in the function. Change the field key
from "jobName" to "job" in the slog.String call to maintain consistent field
naming across all logs, which ensures log queries and correlation are not
fragmented across different field names.
- Around line 231-234: In the error message construction for the GPU scheduling
failure (the msg variable), the example node selectors provided
(kubernetes.io/os=linux and node-role=worker) are generic and don't address the
actual GPU scheduling problem. Replace these generic selector examples with
GPU-specific guidance that remains focused on the nvidia.com/gpu.present=true
selector or the --require-gpu option, so users are directed toward solutions
that actually solve GPU node scheduling instead of generic selectors that won't
fix the problem.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: d3dc1639-4917-4acd-817a-26674403a642

📥 Commits

Reviewing files that changed from the base of the PR and between 57012ca and 4976133.

📒 Files selected for processing (9)
  • pkg/cli/recipe.go
  • pkg/cli/recipe_list.go
  • pkg/cli/recipe_list_test.go
  • pkg/cli/validate.go
  • pkg/logging/cli.go
  • pkg/logging/cli_test.go
  • pkg/serializer/writer.go
  • pkg/serializer/writer_test.go
  • pkg/snapshotter/agent.go

Comment thread pkg/serializer/writer.go Outdated
Comment thread pkg/snapshotter/agent.go
Comment thread pkg/snapshotter/agent.go Outdated
Address the remaining CLI UX items split out from #1361 (the chainsaw
"no such file" symptom was already fixed by the in-process executor):

1. Failed validators no longer print green. The CLI slog handler now
   colors a record red when it carries status=failed/error, even at
   Info level (CTRF logs "validator completed status=failed" at Info).
2. `recipe` completion now lists the resolved component names, not just
   the count.
3. `recipe` and `validate` print a one-line mode banner so it's clear
   whether the run touches a live cluster (recipe is offline; validate
   distinguishes live-cluster vs --no-cluster dry-run).
4. `-o table` no longer garbles on nested values: the flattener renders
   maps, scalar slices, and multi-line strings as single-line compact
   JSON, keeping FIELD/VALUE columns intact while still recursing
   structs and struct slices.
5. `recipe list` table prints a legend explaining that a bare `any`
   criteria value is an intentional wildcard (human-readable surfaces
   only; structured output is unchanged).
6. The agent "pod did not become ready" warning now names the
   namespace and jobName.
7. The "job failed" GPU-scheduling hint now shows concrete,
   repeatable --node-selector key=value syntax.

Closes #1383
@mchmarny mchmarny force-pushed the fix/cli-ux-papercuts branch from 26dc7a0 to d6b824d Compare June 16, 2026 19:23
@mchmarny mchmarny merged commit eea2a81 into main Jun 16, 2026
30 of 32 checks passed
@mchmarny mchmarny deleted the fix/cli-ux-papercuts branch June 16, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/cli size/L theme/validation Constraint evaluation, health checks, and conformance evidence

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Tracker]: validate/recipe CLI UX papercuts (status color, output clarity)

3 participants