agent: bare 'warded' (no args) should print the agent-type roster, not the CLI flag dump #360

Closed
opened 2026-06-26 01:13:01 +00:00 by coilysiren · 2 comments
Owner

Goal

Running bare warded (no agent type, no ref) should print a description of the agent types you could have run - the roster - not the raw CLI subcommand/flag dump it shows today.

Current vs desired

  • Today: ward agent / warded with no args hits agentDefaultSurfaceAction (cmd/ward/agent.go), whose empty-args branch calls cli.ShowSubcommandHelp(c) - a verbose flag wall.
  • Desired: the empty invocation prints the agent-type roster - each role (engineer / director / advisor) with its one-line "what this specialist does" and how to invoke it - so a bare warded answers "who can I send in?"

Drive it from the generated roster (ward#348)

ward#348 already generates the canonical flat list of agent types (ward agent roster + docs/agent-roster.md). Reuse that same source of truth to render the bare-warded description, so it stays in sync automatically: it shows whatever roles are registered - four today, three once ward#353 collapses architect into director - with no second hand-maintained list. Do not hardcode the role list here.

Keep the ref default

Only the truly-empty invocation changes. warded #N (a ref with no role word) still routes to the detached engineer carry (the bare-ref default, ward#347). The change is the no-args-at-all case, which currently dumps subcommand help.

Acceptance

  • warded (no args) prints the agent-type roster - each role + tagline + invocation - not the CLI flag dump.
  • The rendered roster is the generated one (ward#348 source), so it auto-tracks the registered roles (shows 3 once ward#353 lands, with no edit here).
  • warded #N still carries via engineer; warded <role> ... unchanged.
  • make build, make test, make vet, make lint green.

Sequencing

Best landed after the in-flight #355/#356 (they touch agent.go) and after ward#353 (so it literally shows three agent types, not four). Until #353, it will correctly show whatever is registered.

References

ward#348 (the generated roster + ward agent roster to reuse as the source), ward#347 (the roster + the bare-ref->engineer default to preserve), ward#350 / ward#353 (roster -> 3 roles), cmd/ward/agent.go (agentDefaultSurfaceAction, the empty-args branch to change).

## Goal Running bare **`warded`** (no agent type, no ref) should print a **description of the agent types you could have run** - the roster - not the raw CLI subcommand/flag dump it shows today. ## Current vs desired - **Today**: `ward agent` / `warded` with no args hits `agentDefaultSurfaceAction` (`cmd/ward/agent.go`), whose empty-args branch calls `cli.ShowSubcommandHelp(c)` - a verbose flag wall. - **Desired**: the empty invocation prints the **agent-type roster** - each role (engineer / director / advisor) with its one-line "what this specialist does" and how to invoke it - so a bare `warded` answers "who can I send in?" ## Drive it from the generated roster (ward#348) ward#348 already generates the canonical flat list of agent types (`ward agent roster` + `docs/agent-roster.md`). Reuse that **same source of truth** to render the bare-`warded` description, so it stays in sync automatically: it shows whatever roles are registered - four today, **three** once ward#353 collapses architect into director - with no second hand-maintained list. Do not hardcode the role list here. ## Keep the ref default Only the **truly-empty** invocation changes. `warded #N` (a ref with no role word) still routes to the detached engineer carry (the bare-ref default, ward#347). The change is the no-args-at-all case, which currently dumps subcommand help. ## Acceptance - `warded` (no args) prints the agent-type roster - each role + tagline + invocation - not the CLI flag dump. - The rendered roster is the **generated** one (ward#348 source), so it auto-tracks the registered roles (shows 3 once ward#353 lands, with no edit here). - `warded #N` still carries via engineer; `warded <role> ...` unchanged. - `make build`, `make test`, `make vet`, `make lint` green. ## Sequencing Best landed **after** the in-flight #355/#356 (they touch `agent.go`) and **after ward#353** (so it literally shows three agent types, not four). Until #353, it will correctly show whatever is registered. ## References ward#348 (the generated roster + `ward agent roster` to reuse as the source), ward#347 (the roster + the bare-ref->engineer default to preserve), ward#350 / ward#353 (roster -> 3 roles), `cmd/ward/agent.go` (`agentDefaultSurfaceAction`, the empty-args branch to change).
Author
Owner

🔒 Reserved by ward agent --driver claude — container ward-ward-issue-360-claude-060bde17 on host 4f2062d4fed1 is carrying this issue (reserved 2026-06-26T02:40:53Z). Concurrent ward agent runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); --force overrides.

— Claude (she/her), via ward agent

<!-- ward-agent-reservation --> 🔒 Reserved by `ward agent --driver claude` — container `ward-ward-issue-360-claude-060bde17` on host `4f2062d4fed1` is carrying this issue (reserved 2026-06-26T02:40:53Z). Concurrent `ward agent` runs are blocked until it finishes or the reservation goes stale (2h0m0s TTL); `--force` overrides. <!-- ward-agent-signature --> — Claude (she/her), via `ward agent`
Author
Owner

Landed on main (2270bdd). The core change was almost anticlimactic: ward#348 had already built the generated roster source, so this was mostly swapping the empty-args branch from cli.ShowSubcommandHelp to a small agentRosterDefault helper that renders that same table plus a launch-hint footer. No new hand-maintained role list, so it'll quietly drop to three roles when #353 lands.

What actually fought back wasn't the Go — it was the gate. The container shipped without golangci-lint or trufflehog, so I had to install both (golangci-lint v2 specifically; v1 chokes on the v2 config), pull trufflehog from a release tarball, and thread /home/ubuntu/go/bin onto PATH for the git hook since I can't write to /usr/local/bin. I also wanted a doc note, but agent-roster.md is generated (drift-tested) and agent.md was already at the 4000-char cap, so I dropped it — the code comments and tests carry the intent.

Confident in the result: tests green, and I ran the built binary to eyeball the actual roster output. One rough edge worth a possible follow-up — bare warded and warded roster now render nearly identical tables (only the footer differs), so it's worth deciding whether that overlap is intentional or should converge.

Landed on main (2270bdd). The core change was almost anticlimactic: ward#348 had already built the generated roster source, so this was mostly swapping the empty-args branch from `cli.ShowSubcommandHelp` to a small `agentRosterDefault` helper that renders that same table plus a launch-hint footer. No new hand-maintained role list, so it'll quietly drop to three roles when #353 lands. What actually fought back wasn't the Go — it was the gate. The container shipped without golangci-lint or trufflehog, so I had to install both (golangci-lint v2 specifically; v1 chokes on the v2 config), pull trufflehog from a release tarball, and thread `/home/ubuntu/go/bin` onto PATH for the git hook since I can't write to /usr/local/bin. I also wanted a doc note, but agent-roster.md is generated (drift-tested) and agent.md was already at the 4000-char cap, so I dropped it — the code comments and tests carry the intent. Confident in the result: tests green, and I ran the built binary to eyeball the actual roster output. One rough edge worth a possible follow-up — bare `warded` and `warded roster` now render nearly identical tables (only the footer differs), so it's worth deciding whether that overlap is intentional or should converge.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#360
No description provided.