Skip to content

fix(report): keep blueprint-status' count columns when the first row is NOT_DEPLOYED - #374

Merged
neilmartin83 merged 3 commits into
mainfrom
fix/blueprint-status-table-columns
Sep 9, 2026
Merged

neilmartin83 merged 3 commits into
mainfrom
fix/blueprint-status-table-columns

Conversation

@neilmartin83

Copy link
Copy Markdown
Member

Fixes #356.

The bug

A table's columns are the keys of its first row, so a NOT_DEPLOYED blueprint sorting first took SUCCEEDED, FAILED and PENDING off the whole report — while -o json showed the counts on the rows below it, which is what made it read as a rendering fault rather than a missing column. The reporter saw it across three environments; the only predictor was whether the first blueprint was DEPLOYED.

The fix

Per command rather than in the formatter, matching the config list precedent — unioning keys centrally would change every table in the CLI, which CLAUDE.md rules out.

Every row now carries every key, with nil meaning "not applicable to this row", and blueprintStatusRowsForFormat resolves that per format:

  • a structured format (json, json-multi, yaml, ndjson) drops the key, keeping the shape those formats have always emitted
  • every column-rendering format substitutes an em dash, so the key survives as a column whatever the first row happens to be

An em dash rather than 0, because 0 succeeded devices and no deployment to have succeeded on are different facts. -o xml and -o raw count as column-rendering: neither has a case in the formatter's switch, so both render a table and both need the column.

Two adjacent silences, now reported

GetBlueprint and GetBlueprintReport failures were swallowed with if err == nil, so a failed detail fetch left the row claiming no scope and no steps — and if it failed on the first blueprint it took SCOPE and STEPS off the report too, by the same mechanism. Both now warn to stderr and leave the cell not-applicable.

Tests

TestReportBlueprintStatusRendersEveryColumnFromTheWire drives the command over the reported wire shape through an httptest server, so it fails if the command stops carrying a key on a row that has no count — the resolver tests take the canonical rows as given and cannot see that. Verified failing against the previous row build, with exactly the reported output.

Wire verification

Live EU environment, 23 blueprints, first two rows NOT_DEPLOYED — the shape the issue needs. Before and after run against the same tenant minutes apart.

Before (main):

 NAME                                         SCOPE   STATE          STEPS
                                              0       ○ NOT_DEPLOYED     1
 TEST                                         1       DEPLOYED       1

After:

 NAME                                         FAILED   PENDING   SCOPE   STATE          STEPS   SUCCEEDED
                                              —        —         0       ○ NOT_DEPLOYED     1       —
 TEST                                         0        0         1       DEPLOYED       1       1
 Claude Coder and Desktop Governance Policy   3        2         1       DEPLOYED       1       0
 OS updates                                   0        6         8       DEPLOYED       1       0

All six formats exercised, exit 0 and empty stderr on each (so neither new warning fired — every fetch succeeded):

format result
table 7 columns, placeholders
csv header + 23 rows, all 7 fields
plain 23 rows, 7 fields each
json / yaml / ndjson 0 em dashes; NOT_DEPLOYED rows carry 4 keys, DEPLOYED rows 7

go build, full go test ./... and make lint (0 issues) all clean.

🤖 Generated with Claude Code

…is NOT_DEPLOYED

A table's columns are the keys of its *first* row, so a NOT_DEPLOYED
blueprint sorting first took SUCCEEDED, FAILED and PENDING off the whole
report — while `-o json` showed the counts on the rows below it, which is
what made it read as a rendering fault rather than a missing column.
Three environments reproduced it; the only predictor was whether the
first blueprint was DEPLOYED.

Fixed per command rather than in the formatter, matching `config list`:
unioning keys centrally would change every table in the CLI, which
CLAUDE.md rules out. Every row now carries every key, with nil meaning
"not applicable to this row", and blueprintStatusRowsForFormat resolves
that per format — a structured format (json, json-multi, yaml, ndjson)
drops the key, keeping the shape those formats have always emitted, and
every column-rendering format substitutes an em dash. An em dash rather
than 0, because 0 succeeded devices and no deployment to have succeeded
on are different facts. -o xml and -o raw count as column-rendering:
neither has a case in the formatter's switch, so both render a table.

Two adjacent silences are now reported. GetBlueprint and
GetBlueprintReport failures were swallowed with `if err == nil`, so a
failed detail fetch left the row claiming no scope and no steps — and if
it failed on the *first* blueprint it took SCOPE and STEPS off the report
too, by the same mechanism. Both now warn to stderr and leave the cell
not-applicable.

TestReportBlueprintStatusRendersEveryColumnFromTheWire drives the command
over the reported wire shape, so it fails if the command stops carrying a
key on a row that has no count; the resolver tests take the canonical
rows as given and cannot see that. Verified failing against the previous
row build, with exactly the reported output.

Fixes #356

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@neilmartin83
neilmartin83 merged commit babf440 into main Sep 9, 2026
1 check passed
@neilmartin83
neilmartin83 deleted the fix/blueprint-status-table-columns branch September 9, 2026 09:57
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.

pro report blueprint-status columns missing in table output

2 participants