plan: align display across plan-family commands; surface CreatedBy#331
Merged
Conversation
The plan-family commands had drifted from each other in several small ways since the previous PR. Audit + fixes: - plan tag get rendered the embedded plan as a thin metadata blurb (ID, Steps count, prompt first line, Created) — the shape we replaced in plan get during the previous PR. It now embeds the full plan body (Inputs / Steps / Outputs sections) using the same arrow form plan get uses. Plan-level metadata is omitted: ID and SelectionHint already appear in the tag header above; the rest is one signadot plan get away. The tag header also gains a Selection Hint: line so plan tag list and plan tag get agree on what summarises a tag. To make this shareable without a circular import (plan imports plantag for tag-application after compile/create), the plan-detail printer moved into the planshared package as PrintPlanDetails alongside a PrintPlanBody variant that skips the top-level header for embedded use. plan/printers.go collapses to a thin wrapper. - Surface PlanStatus.CreatedBy (added in the latest go-sdk drop) as a Created By: row in the plan header — used by plan get, compile, create, recompile, run, and the embedded view in plan tag get (where it renders as Plan Created By: to disambiguate against the tag-level Created/Updated fields). Resolution by ActorType: user → email, api_key → "api key" + masked id, system → "system". - plan action get's Outputs table no longer carries REQUIRED / DEFAULT columns. Those are input concepts that always rendered as false / empty for outputs (review feedback on PR #325 that hadn't landed). Separate row type with just NAME / SCHEMA. - planrunnergroup/printers.go: migrate inline time.Parse + timeago.NoMax to utils.TimeAgo, matching the cleanup we'd already done in plantag and planexec. Drops the time and timeago imports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
davixcky
approved these changes
May 7, 2026
Empty-string values previously collapsed to the same shape as
nil/missing values: name (set in plan) with no detail. That hides
the distinction between "value not provided" and "deliberately
empty," which matters when an action interprets the empty string
specifically — e.g. run-image treats image:"" as "run on the host
runner without a container," a meaningful authoring choice the
reader needs to see.
Now an empty string renders as the literal "" (with quotes):
image ← "" (set in plan)
and an unset/nil value still renders as no-detail:
image (set in plan)
Same disambiguation applies wherever FormatValue is used (plan
get's plan-level Inputs, plan x get's resolved inputs, plan get's
declared param defaults, output rows). Scalars still pass through
unchanged; objects and arrays continue to round-trip through
json.Marshal.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
I think it’s fine as it is, as we are not rendeing action bodies, even for larger plans it remains fairly readable (as shown below). That said, I’d also like to hear @foxish and @scott-cotton’s thoughts. $ signadot plan get rfy1vrt9m9p70
ID: rfy1vrt9m9p70
Selection Hint: Hotrod-istio health/dispatch/load checks; image is a plan param so callers can pin a runc image or "" to run on the host runner.
Cluster: pattern "signadot-staging"
Created: Thu, 07 May 2026 10:38:35 -03 (32 seconds ago)
Inputs:
frontend_url ← http://frontend.hotrod-istio.svc:8080 (default)
location_url ← http://location.hotrod-istio.svc:8081 (default)
runner_image ← "" (default)
Steps:
frontend_health
action: run-image (vjpm3jvtwkxu2) (revision 2)
inputs:
image ← params.runner_image (ref)
script ← STATUS=$(curl -s -o "$TMPDIR/body.html" -w '%{http_code}' --max-time 10 "$(cat .… (3 lines) (set in plan)
url ← params.frontend_url (ref)
outputs:
result schema: object
location_health
action: run-image (vjpm3jvtwkxu2) (revision 2)
inputs:
image ← params.runner_image (ref)
script ← URL="$(cat ./context/url)/locations"… (7 lines) (set in plan)
url ← params.location_url (ref)
outputs:
result schema: object
dispatch_ride
action: run-image (vjpm3jvtwkxu2) (revision 2)
inputs:
frontend_ok ← steps.frontend_health.outputs.result (ref)
frontend_url ← params.frontend_url (ref)
image ← params.runner_image (ref)
script ← FRONTEND="$(cat ./context/frontend_url)"… (9 lines) (set in plan)
outputs:
result schema: object
load_test
action: k6 (0fk4dk2myr0h2) (revision 2)
inputs:
frontend_ok ← steps.frontend_health.outputs.result (ref)
script ← import http from 'k6/http';… (32 lines) (set in plan)
target_url ← params.frontend_url (ref)
verify_all
action: check (0t57r22fxdvjb) (revision 12)
inputs:
dispatch ← steps.dispatch_ride.outputs.result (ref)
expression ← frontend.healthy == true && location.healthy == true && location.locationCount >… (set in plan)
frontend ← steps.frontend_health.outputs.result (ref)
location ← steps.location_health.outputs.result (ref)
name ← hotrod-all-checks (set in plan)
Outputs:
check ← steps.verify_all.outputs.result
dispatch ← steps.dispatch_ride.outputs.result
frontend ← steps.frontend_health.outputs.result
location ← steps.location_health.outputs.result
|
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.
Summary
Audit + alignment of the plan-family commands' rendered output, on top of #326. Five small things that had drifted apart:
plan tag getnow embeds the full plan body (Inputs / Steps / Outputs in the arrow form) instead of the old thin metadata blurb (ID, Steps count, prompt first line, Created). The tag header gains aSelection Hint:line soplan tag listandplan tag getagree on what summarises a tag.plantagwithout a circular import (plan → plantag exists for tag-application), the plan-detail printer moved intoplansharedasPrintPlanDetailsalongside aPrintPlanBodyvariant that skips the top-level header for embedded use.plan/printers.gocollapses to a thin wrapper.Created Bysurfaced (newPlanStatus.CreatedByfrom the latest go-sdk). Renders in the plan header forplan get/ compile / create / recompile / run, and asPlan Created By:inplan tag get's tag header. Resolution byActorType:user→ email,api_key→"api key " + masked id,system→"system".plan action getOutputs table dropsREQUIRED/DEFAULTcolumns — they're input concepts that always rendered asfalse/empty for outputs. Review feedback on Add plan action list/get commands #325 that hadn't landed.planrunnergroupcleanup: migrate inlinetime.Parse + timeago.NoMaxtoutils.TimeAgo, matching the cleanup we'd already done inplantagandplanexec.Examples
plan get(withCreatedBy)plan tag get(before / after)Before — thin embedded summary, no selection hint:
After — full embedded plan body, hint at top,
Plan Created By:for unambiguity against the tag-levelCreated/Updated:plan action getOutputs tableBefore (REQUIRED / DEFAULT always empty for outputs):
After:
Files touched
internal/command/planshared/plan.go— new file:PrintPlanDetails,PrintPlanBody, plan rendering moved in fromplan/printers.gointernal/command/planshared/render.go—FormatCreatedByhelperinternal/command/plan/printers.go— collapsed to a thin wrapper aroundplanshared.PrintPlanDetailsinternal/command/plantag/printers.go— embedPrintPlanBodyin tag get, addSelection HintandPlan Created Byto the tag headerinternal/command/planaction/printers.go— separate row type for action outputs (drops REQUIRED/DEFAULT)internal/command/planrunnergroup/printers.go— migrate toutils.TimeAgogo.mod/go.sum— bump go-sdk to the tip ofmainwithPlanStatus.CreatedByTest plan
signadot plan get <id>showsCreated By:(system / user email / api key) when populatedsignadot plan tag get <name>shows the full embedded Inputs/Steps/Outputs andPlan Created By:signadot plan action get <name>Outputs table has justNAME/SCHEMAsignadot planrunnergroup listCREATEDcolumn renders compactly ("X days ago")signadot plan tag listSELECTION HINTcolumn unchanged