fix(report): keep blueprint-status' count columns when the first row is NOT_DEPLOYED - #374
Merged
Merged
Conversation
…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
enabled auto-merge
September 9, 2026 09:46
grahampugh
approved these changes
Sep 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #356.
The bug
A table's columns are the keys of its first row, so a
NOT_DEPLOYEDblueprint sorting first tookSUCCEEDED,FAILEDandPENDINGoff the whole report — while-o jsonshowed 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 wasDEPLOYED.The fix
Per command rather than in the formatter, matching the
config listprecedent — unioning keys centrally would change every table in the CLI, which CLAUDE.md rules out.Every row now carries every key, with
nilmeaning "not applicable to this row", andblueprintStatusRowsForFormatresolves that per format:json,json-multi,yaml,ndjson) drops the key, keeping the shape those formats have always emittedAn em dash rather than
0, because 0 succeeded devices and no deployment to have succeeded on are different facts.-o xmland-o rawcount 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
GetBlueprintandGetBlueprintReportfailures were swallowed withif 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 tookSCOPEandSTEPSoff the report too, by the same mechanism. Both now warn to stderr and leave the cell not-applicable.Tests
TestReportBlueprintStatusRendersEveryColumnFromTheWiredrives 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):After:
All six formats exercised, exit 0 and empty stderr on each (so neither new warning fired — every fetch succeeded):
—placeholdersNOT_DEPLOYEDrows carry 4 keys,DEPLOYEDrows 7go build, fullgo test ./...andmake lint(0 issues) all clean.🤖 Generated with Claude Code