Skip to content

fix(derive): three more descriptions a spec keeps and the derive lost - #861

Merged
jdx merged 2 commits into
agent/help-bodyfrom
agent/help-long
Aug 13, 2026
Merged

fix(derive): three more descriptions a spec keeps and the derive lost#861
jdx merged 2 commits into
agent/help-bodyfrom
agent/help-long

Conversation

@jdx

@jdx jdx commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Found while starting on --help, which reads the long forms the short one does not.

A variant's short description was hiding the struct's long one. meta_overrides chose both
from the variant when the variant had either, so the shape every generated CLI has — the enum
says what a command is for in a line, the struct's own comment carries the detail — lost the
detail entirely. Each falls back on its own now.

A doc comment's lines were trimmed one by one, which flattened every indented block in a CLI's
help. An indented block is how a spec shows a command to type, and mise's help is full of them.
Only the single space /// conventionally adds is stripped now, and trailing space.

A program could not describe itself twice over. A comment's long form always contains its short
one, because the short form is the comment's first paragraph — where a spec keeps about and
about_long independent, and mise's are entirely different sentences. #[usage(about = …, long_about = …)] declares them, and the generator uses it when a comment cannot say both.

The --help layout these were found by is written but not yet at parity — 123 of 211 pages
still differ, each remaining cause another metadata path where the shadow's description is not
the spec's. It is held back rather than shipped wrong, and the plan says so.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com


Stack created with GitHub Stacks CLIGive Feedback 💬


Note

Low Risk
Cold-path help/spec metadata and test fixtures only; parsing and -h parity (211/211) are unchanged.

Overview
Fixes three metadata round-trip gaps in usage-derive that showed up while chasing --help parity with usage-lib (still held back at 123/211 pages).

Subcommand help: meta_overrides no longer drops a struct’s long description when the enum variant only supplies a short one—short and long now fall back independently, matching the usual “variant line + struct detail” layout.

Doc comments: doc_comment stops trimming each /// line, so indented examples in long help keep their spacing.

Root about / about_long: Adds #[usage(about = …, long_about = …)] when the two strings are not the first-paragraph relationship doc comments force. Shadow generation (xtask) emits the same attributes for usage and clap fixtures; mise shadows pick up explicit about text.

Conformance tests cover the split-description fixture; PLAN.md records the fixes and that full --help layout is not shipped yet.

Reviewed by Cursor Bugbot for commit 3c6fc19. Bugbot is set up for automated code reviews on this repo. Configure here.

How these were found

By starting on --help. The wider layout reads the long form of every description, which the
short form never touches — so three more places where a spec says something the derive could not
keep surfaced at once.

what happened
a variant's short description hid the struct's long one meta_overrides chose both from the variant when it had either. That is the shape every generated CLI has — the enum names the command in a line, the struct's comment carries the detail — so the detail was lost for all of them
a doc comment's lines were trimmed one by one which flattened every indented block in help. An indented block is how a spec shows a command to type, and mise's help is full of them
a program could not describe itself twice over a comment's long form always contains its short one, since the short form is the comment's first paragraph. A spec keeps about and about_long independent, and mise's are entirely different sentences

What is not here

The --help renderer itself. It is written, and it is at 123 of 211 pages differing — each
remaining cause another metadata path where the shadow's description is not the spec's. Shipping
a public long_help that is wrong on more than half of a real CLI's pages would be worse than
not shipping it, so it is held back and the plan records the count rather than the intention.

The three fixes above stand on their own: they are round-trip fidelity, which docs, manpages,
completions and the SDK generators all read.

Verification

  • Three tests on a fixture shaped like a generated CLI — short description on the variant, long
    on the struct, an indented example inside it, and a program whose two descriptions differ.
  • All three mutation-checked: restoring each old behaviour fails exactly its own test.
  • -h parity is unaffected and still 211 of 211, which is the guard against these fixes
    changing the short form.

AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: unavailable.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: e26c4c4f-8f28-48e6-8dcd-cec329a81763

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR improves description fidelity in generated CLI metadata.

  • Preserves struct long descriptions when variants provide only short descriptions.
  • Retains indentation in doc-comment examples.
  • Supports independent root about and long_about values in derives and generated shadows.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
derive/src/model.rs Adds independent root-description attributes and preserves meaningful doc-comment indentation.
derive/src/codegen.rs Makes variant short- and long-description fallback independent.
xtask/src/shadow.rs Emits explicit root descriptions when they cannot be represented faithfully by one doc comment.
conformance/tests/metadata.rs Adds end-to-end coverage for split descriptions, indentation preservation, and parsing stability.

Reviews (4): Last reviewed commit: "fix(derive): keep a short-only flag's va..." | Re-trigger Greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9ea3f1a. Configure here.

Comment thread xtask/src/shadow.rs
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Instruction counts

benchmark trend instructions Δ wall (min) Δ
markdown ▁▁▁▁▁▂▂▂██ 175,245,063 → 175,122,454 -0.07% 16.93 → 15.96ms -5.73%
startup ▁▁▁▁▁▁▁▁██ 1,222,129 → 1,222,008 -0.01% 1.00 → 0.95ms -4.26%

No instruction-count regression above 1%.

Only instruction counts gate. Wall clock is shown for context — on identical hardware it moves 4-20% run to run.

Measured by tak — instruction-counted CLI benchmarks, stored in this repository's git notes.

Shadow comparison

Parsing mise use -g node@20 against a shadow of mise's committed spec.
Reported, not gated: the shadow grows as the derive learns to express more, so
what to watch is the ratio rather than either column.

usage clap ratio
instructions, cold parse 29877 5875919 196x
usage: argv -> struct                             850 ns      0.85 µs
clap: build tree + parse -> struct             491683 ns    491.68 µs
clap: parse -> struct, tree reused              23253 ns     23.25 µs
clap: build tree only                          302916 ns    302.92 µs

3c6fc19c6a78 vs fe13b0b9c7d8 · measured on the runner, not pushed to the history.

@jdx
jdx force-pushed the agent/help-long branch from 17b9971 to 5314570 Compare August 13, 2026 18:10
jdx and others added 2 commits August 13, 2026 18:48
Found while starting on `--help`, which reads the long forms the short one does not.

A variant's short description was hiding the struct's long one. `meta_overrides` chose both
from the variant when the variant had *either*, so the shape every generated CLI has — the enum
says what a command is for in a line, the struct's own comment carries the detail — lost the
detail entirely. Each falls back on its own now.

A doc comment's lines were trimmed one by one, which flattened every indented block in a CLI's
help. An indented block is how a spec shows a command to type, and mise's help is full of them.
Only the single space `///` conventionally adds is stripped now, and trailing space.

A program could not describe itself twice over. A comment's long form always contains its short
one, because the short form *is* the comment's first paragraph — where a spec keeps `about` and
`about_long` independent, and mise's are entirely different sentences. `#[usage(about = …,
long_about = …)]` declares them, and the generator uses it when a comment cannot say both.

The `--help` layout these were found by is written but not yet at parity — 123 of 211 pages
still differ, each remaining cause another metadata path where the shadow's description is not
the spec's. It is held back rather than shipped wrong, and the plan says so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…'s about

Two findings from Cursor Bugbot, both regressions from this stack.

A flag is named after the form it answers to, and for a short-only flag that form is one
character — right for the flag's name and useless as the name of its *value*, since help and the
KDL both fall back to `flag.name` for the placeholder. `-j <j>` where the field is called
`jobs`. The descriptive name is kept as the value name before the flag's own is overwritten.

And when a program's two descriptions are independent, the generator skipped the root's doc
comment and wrote them into the *usage* attribute list only — which the clap dialect never
emits, so the clap shadow stopped describing the program at all. clap takes an independent
`about` and `long_about`, and a fixture for comparing two frameworks cannot have one of them
missing the CLI's own description.

Both mutation-checked. `-h` parity is unchanged at 211 of 211, which is what says the value-name
fix did not move the rendering.

Two older findings on #854 were already answered by the `demanded`/`flag_demanded` helpers: a
defaulted argument or flag is one the parser fills, so the usage line brackets it as optional.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jdx
jdx force-pushed the agent/help-long branch from 5314570 to 3c6fc19 Compare August 13, 2026 18:54
@jdx
jdx merged commit 505e559 into main Aug 13, 2026
9 checks passed
@jdx
jdx deleted the agent/help-long branch August 13, 2026 20:18
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