Skip to content

feat: print the CLI surface on demand - #12

Merged
matheusPavaneli merged 1 commit into
mainfrom
WB-18-surface
Aug 22, 2026
Merged

feat: print the CLI surface on demand#12
matheusPavaneli merged 1 commit into
mainfrom
WB-18-surface

Conversation

@matheusPavaneli

Copy link
Copy Markdown
Owner

What

wb surface prints every group, action and flag, walked from build_parser().

A session composing an unfamiliar call had to infer flags from prose in a SKILL.md, and prose is where a flag that never existed comes from — wb pr check --key ABC-1 was written that way and refused by argparse. test_plugin.py already holds every command to being named somewhere a session reads; naming is not knowing what it takes.

It reports what the invented calls get wrong: which arguments are positional, which are required, which take no value, and the closed set a choice flag allows.

$ wb surface pr
wb pr context   branch, commits, plan summary, verification verdict
  key   [positional; required]
  --base <value>
  --target <value>
wb pr check   reject filler, empty sections and placeholders in a draft
  --file <value>   [required]
  --shape <value>   [one of: trivial, small, large]

This is the schema MCP publishes for every tool in the system prompt of every session, used or not. Here it is complete and costs nothing until something asks — the same trade wb route made by being a command rather than an eleventh skill. No SKILL.md names it; the README does.

Walked rather than kept by hand, because a hand-kept list of flags is a second description of the CLI, and a second description is the thing that drifts.

Verification

python -m unittest discover -s tests -q     641 tests, OK (skipped=4)

7 new tests, including the one that matters: wb surface pr --json names exactly --file and --shape, and asserts --key is absent.

One regression is covered because it happened during the work: the positional was first named group, which is the dest the top-level parser already owns, so wb surface task overwrote it and dispatched to wb task instead. Renamed to of with metavar GROUP, with a test that naming a group prints it rather than running it.

Risk and rollback

New command, nothing existing changed. contract.VERSIONS gains surface: 1. Revert the commit to remove it.

A session composing an unfamiliar call had to infer the flags from prose
in a SKILL.md, and prose is where a flag that never existed comes from:
`wb pr check --key ABC-1` was written that way and refused by argparse.

`test_plugin.py` already holds every command to being *named* somewhere a
session reads. Naming is not knowing what it takes.

`wb surface` walks `build_parser()`, so it reports the arguments the CLI
actually accepts and cannot drift from them -- a hand-kept list of flags
would be a second description of the CLI, which is the thing that drifts.
It carries what the invented calls get wrong: which arguments are
positional, which are required, which take no value, and the closed set a
choice flag allows.

This is the schema MCP publishes for every tool in the system prompt of
every session, used or not. Here it is complete and costs nothing until
something asks for it -- the same trade `wb route` made by being a command
rather than an eleventh skill.

Refs WB-18
@matheusPavaneli
matheusPavaneli merged commit c83c9a1 into main Aug 22, 2026
8 checks passed
matheusPavaneli added a commit that referenced this pull request Aug 22, 2026
Five merged PRs sat on main under a 0.6.0 version string: #10, #11, #12,
#13 and #14. The marketplace compares declared versions, so a string
that does not move is a release nobody receives -- the same failure #11
was written to catch, one release later and from the other side. The gate
holds the declared version to a released changelog section; it cannot
hold main to declaring the work that landed on it.

Three commands gained surface -- `wb surface`, `wb status --stats
--global`, `wb task clean --merged/--older-than` -- so this is a minor
bump. No breaking change: every existing group, action, flag and exit
code behaves as it did in 0.6.0, and no `--json` payload lost or renamed
a key.

Co-authored-by: matheusPavaneli <matheusPavaneli@users.noreply.github.com>
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.

1 participant