# Plan: expand clap doc comments for v0.2.0 manpages

**Status:** phases 1–3 complete (top-level `Cli`, 14 `Commands`
variants, 51 action variants, and per-flag detail on every option
that conflicts, gates behavior, accepts a structured value, or has
non-obvious defaults / env-var fallback / stdin behavior); phase 4
contingent. Operational style guide:
[`docs/dev/cli-doc-style.md`](../dev/cli-doc-style.md).

## Phase 1 results (2026-05-02)

Confirmed and adjusted:

- `verbatim_doc_comment` is required on items whose long body contains
  an indented example block. Without it, `clap_mangen` collapses the
  examples into a single space-separated line. (Settles §5.1.)
- **Indent example blocks at 2 spaces, not 4.** A 4-space indent
  triggers rustdoc's CommonMark code-block detection, and rustdoc
  attempts to compile the lines as Rust, failing every doctest. A
  2-space indent is treated as a paragraph by rustdoc (no compilation)
  but is preserved verbatim by `clap_mangen` when
  `verbatim_doc_comment` is set. **This supersedes the 4-space
  examples in §1.1–1.3.**
- **ASCII only** in doc comments. Em dashes (`—`), en dashes, and
  curly quotes round-trip through the roff pipeline as mojibake
  (e.g. `â`). Use `--`, `-`, and straight quotes.
- Clippy's pedantic `doc_markdown` flags bare URLs and ALL_CAPS / CamelCase
  identifiers in shell examples. Wrapping them in `<>` or backticks
  would degrade copy-paste UX. Suppress with
  `#[expect(clippy::doc_markdown, reason = "...")]` at the smallest
  enclosing item (the project denies bare `#[allow]`).
- `cargo run -p xtask -- man --out man/man1` regenerates the pages;
  the resulting diff for phase 1 was contained to the 15 affected
  pages (`bzr.1` plus the 14 group pages).

## Original plan
**Target release:** v0.2.0 (first widely-consumed release).
**Scope:** every doc comment under `src/cli/*.rs`.
**Output target:** `man/man1/*.1` files generated by `cargo run -p xtask -- man` (clap_mangen 0.3) — currently 66 pages, all with one-line DESCRIPTIONs.
**Code changes required:** zero clap attributes need to be added in the common case. Doc comments alone produce both `about` (short, NAME line) and `long_about` (DESCRIPTION) when they contain a blank `///` line separator. The one exception is `verbatim_doc_comment` for the rare flag whose long help needs ASCII tables or fixed-width examples — see Risks (§5.1).

## Background

Today's manpages are sparse because every `///` doc comment in `src/cli/` is a single line and there's no use of `long_about` / `long_help` / `after_help` / `verbatim_doc_comment`. Render of `bzr-bug-create.1`:

```
DESCRIPTION
       Create a new bug
```

That's the whole DESCRIPTION section. Same shape on every subcommand page. Since v0.2.0 will be the first widely-consumed release, the docs need production-grade content rather than terse summaries.

clap-derive's preprocessing rule is the load-bearing fact:

- The first paragraph (everything before the first `///`-only blank line) becomes `about`/`help`. This shows up in `bzr --help` summaries, parent-command listings, and the man page NAME line.
- The full text becomes `long_about`/`long_help`. This shows up in `bzr <cmd> --help` (long form) and the man page DESCRIPTION (for command-level docs) or per-flag detail block (for arg-level docs).
- Inside each paragraph, newlines collapse to spaces and blank lines collapse to one — fine for prose, fatal for ASCII tables. Use `#[command(verbatim_doc_comment)]` or `#[arg(verbatim_doc_comment)]` only when fixed-width formatting is essential.
- A trailing period on the last sentence of the *short* paragraph is stripped by clap. Keep that paragraph a single declarative sentence.

## 1. Style guide

### 1.1 Top-level (`Cli` in `src/cli/mod.rs`) — produces `bzr.1`

The bzr(1) page is the entry point. It needs to introduce the tool, call out global behavior that affects every subcommand, and point at the per-resource pages. Today it just says "A CLI for Bugzilla" twice.

Target shape:

```rust
/// A command-line client for Bugzilla REST API servers.
///
/// bzr provides scriptable access to bugs, comments, attachments,
/// products, components, users, and groups across one or more named
/// Bugzilla servers. It is modeled on the GitHub CLI (`gh`): every
/// resource is a top-level subcommand, every action is a verb under
/// that resource, and `--json` is supported on read paths so output
/// can be consumed by downstream tools.
///
/// Configuration lives in `~/.config/bzr/config.toml` and stores one
/// or more named servers. Use `bzr config set-server` to add a server
/// and `bzr config set-default` to pick the one used when `--server`
/// is omitted. API keys can be stored inline, in an environment
/// variable, or in the OS keychain (`bzr config set-keyring`).
///
/// Output defaults to a colored table at a TTY and to JSON when
/// stdout is piped. Use `--json` or `BZR_OUTPUT=json` to force JSON.
/// Exit codes are stable and documented in bzr-cli(7); the most
/// common are 0 (success), 2 (not found or bad args), 4 (Bugzilla
/// API error), 9 (auth), and 13 (TLS pin mismatch).
///
/// See bzr-bug(1), bzr-config(1), bzr-comment(1), bzr-attachment(1),
/// bzr-product(1), bzr-user(1), bzr-group(1), bzr-template(1),
/// bzr-query(1), bzr-server(1), bzr-classification(1),
/// bzr-component(1), bzr-field(1), and bzr-whoami(1) for the
/// per-resource reference pages.
#[derive(Parser)]
#[command(name = "bzr", version)]
pub struct Cli { ... }
```

Notes:
- Drop the `about = "A CLI for Bugzilla"` attribute. Once the doc comment is present, `#[command]` will source `about`/`long_about` from it.
- The first sentence is the NAME line. Keep it declarative.
- Cross-reference style: `bzr-bug(1)` (man-page convention) — these names match the generated filenames so packagers can hyperlink them.
- Mention env vars only when they have user-facing impact (`BZR_OUTPUT`, `RUST_LOG`, `NO_COLOR`). Defer the full table to `docs/bzr-cli.md`.

### 1.2 Subcommand groups (`Commands` variants in `src/cli/mod.rs`) — produce `bzr-bug.1` etc.

Each variant currently has one terse line ("Bug operations"). The man page that gets generated for the parent command lists its actions but has no orientation prose. Target shape:

```rust
/// Operate on bugs: list, view, search, create, clone, update, history.
///
/// The `bug` group is the most commonly used part of bzr. Read paths
/// (`list`, `view`, `search`, `history`, `my`) work without any
/// authentication beyond what the configured server requires; write
/// paths (`create`, `clone`, `update`) require credentials and the
/// caller must have appropriate Bugzilla permissions on the target
/// product.
///
/// Filter flags (`--product`, `--component`, `--status`, `--assignee`,
/// `--creator`, `--priority`, `--severity`) on `list` and `my` are
/// repeatable for OR semantics and accept a `!` prefix for NOT
/// (e.g. `--status '!CLOSED'`).
///
/// Examples:
///
///     bzr bug list --product Firefox --status NEW --limit 25
///     bzr bug view 12345
///     bzr bug create --product P --component C --summary "..."
///     bzr bug update 100 200 --status RESOLVED --resolution FIXED
///
/// See bzr-bug-list(1), bzr-bug-view(1), bzr-bug-search(1),
/// bzr-bug-history(1), bzr-bug-my(1), bzr-bug-create(1),
/// bzr-bug-clone(1), and bzr-bug-update(1) for per-action detail.
Bug {
    #[command(subcommand)]
    action: BugAction,
},
```

Conventions for this level:
- One-sentence orientation in the short paragraph; lead with the verbs covered.
- Long body covers (a) auth/permission expectations, (b) any cross-cutting flag semantics that recur across actions in the group, (c) 2–4 representative examples, (d) cross-references to the per-action manpages.
- Examples are indented four spaces. Clap collapses newlines inside a paragraph but treats indented runs as their own paragraphs in practice; if rendering of these in the man page is wrong, switch the variant to `verbatim_doc_comment`. Validate during phase 1 (see §4).

### 1.3 Action variants (e.g. `BugAction::Create`) — produce `bzr-bug-create.1` DESCRIPTION

This is the bulk of the work and where v0.2.0 readers will spend the most time. Today's DESCRIPTION ("Create a new bug") is unhelpful. Target shape:

```rust
/// Create a new bug under a product and component.
///
/// Files a new bug on the configured server. `--summary` is always
/// required. `--product` and `--component` are required unless a
/// saved template (selected with `--template`) provides them; values
/// passed on the command line override values from the template.
/// Some Bugzilla installations also require `--op-sys` and
/// `--rep-platform` — when omitted on those servers, the call fails
/// with an API error (exit code 4).
///
/// On success, prints the new bug ID and URL to stdout (or a JSON
/// object with `id`, `url`, and `summary` when `--json` is set).
///
/// Examples:
///
///     bzr bug create --product Fedora --component kernel \
///       --summary "Boot failure on 6.x" \
///       --description "System hangs at initramfs" \
///       --priority high --severity major
///
///     bzr bug create --template security-bug \
///       --summary "XSS in login form"
///
/// Exit codes: 0 on success, 2 on missing required field (when no
/// template is provided), 4 on Bugzilla API error, 7 on input
/// validation (e.g. empty summary), 9 on authentication failure.
///
/// See also bzr-bug-clone(1) for cloning an existing bug,
/// bzr-template(1) for managing the templates referenced by
/// `--template`, and bzr-field(1) for discovering valid values for
/// `--priority`, `--severity`, and `--status`.
Create {
    /// Use a saved template for default field values.
    ///
    /// ...
}
```

Per-action checklist (every action must hit each of these in its long body):

| Section | When to include | Example |
|---|---|---|
| What it does | always — second paragraph | "Files a new bug on the configured server." |
| Required vs. conditional vs. optional inputs | always when more than one flag | the `--summary` / `--product` / `--component` / `--template` rule above |
| Output shape | when output is more than "the resource" | "On success, prints the new bug ID and URL." |
| Side effects beyond the obvious | when present | "Adds a 'Cloned from bug #N' comment unless `--no-comment`." |
| Examples | always; minimum 1, ideally 2 | indented four spaces |
| Exit codes | when behavior differs from generic 0/1 | `Create` may exit 2 (missing field), 4 (API), 9 (auth) |
| Env-var and stdin behavior | when the command reads them | `comment add` reads `$EDITOR` and stdin |
| Cross-references | when a related command exists | "See also bzr-bug-clone(1)." |

Reuse `docs/bzr-cli.md` as the source of truth for examples — copy them verbatim where possible so the two docs don't drift.

### 1.4 Individual args / options — produce per-flag detail block

Args are the most numerous (≈140 across the tree) and the easiest to over-document. Most are fine with a one-line short paragraph and a one-paragraph long body that adds the conventions a reader needs to predict behavior.

Default shape — one paragraph, kept short, sufficient for 80% of flags:

```rust
/// Filter by product name. Repeatable for OR semantics; prefix with `!` to exclude.
#[arg(long)]
product: Vec<String>,
```

Expanded shape — when the flag has non-obvious interactions, units, or accepted values:

```rust
/// Path to a PEM-encoded CA certificate file used to verify TLS for this server.
///
/// When set, bzr will require the server's certificate chain to
/// verify against this CA instead of (or in addition to) the OS
/// trust store. Useful for self-hosted Bugzilla instances behind a
/// private CA. Mutually exclusive with `--tls-insecure`,
/// `--tls-pin-sha256`, and `--tls-pin-now`. To remove a previously
/// configured CA cert, run `bzr config set-server <name>
/// --tls-pin-clear` (which clears both pin types).
#[arg(long, conflicts_with_all = ["tls_insecure", "tls_pin_sha256", "tls_pin_now"])]
tls_ca_cert: Option<String>,
```

Per-arg conventions:
- **Always document repeatability and negation** (`!` prefix) when the type is `Vec<String>`. The current help text already does this for `bug list` filters; replicate verbatim for the same flags on `bug my` and `query save`.
- **Always document accepted values** for enum-typed flags (`--type`, `--auth-method`, `--api`, `--output`). Don't enumerate where clap will already enumerate; do mention default.
- **Document mutual exclusion** in the long body. clap does enforce conflicts via `conflicts_with`, but its help message just says "cannot be used with X" — a reader benefits from "use Y instead" hints.
- **Mention env-var fallback or stdin behavior** where present (`--body` on `comment add`, `--api-key` vs `--api-key-env`).
- **Don't repeat the obvious.** If the short doc already says "Bug ID", the long body adds nothing. Only expand when there's something to add.
- **Examples in arg docs are rare** — use them only for syntax-heavy flags like `--flag` (review syntax) or `--from-url` (URL recognition rules).

Quick rubric to decide whether an arg deserves a long paragraph:
- Does it conflict with another flag? → expand
- Does it have a non-obvious unit or default? → expand
- Does it accept a structured value (URL, flag-syntax, ID-list)? → expand
- Does it gate behavior elsewhere (`--all`, `--template`, `--save-as`)? → expand
- Is it just `Bug ID` or a one-line description? → leave alone

### 1.5 Cross-cutting conventions

- **Line length:** 100 cols hard, but doc comments wrap at the source line, so line wrapping in source = whitespace-collapsed in render. Aim for 78–88 chars in the source for readable diffs.
- **Backticks** render as `\fR<text>\fR` in roff, fine. Use them around literal flag names, env vars, file paths, and code identifiers. Don't use them for emphasis.
- **No phantom features** (CLAUDE.md). Cross-check every new "see also" or example against `docs/bzr-cli.md` to make sure the referenced flag exists.
- **No "previously this used to..."** (CLAUDE.md "replace, don't deprecate").
- **Exit code mentions:** prefer named codes ("exit code 4 on Bugzilla API error") over bare numbers. The full table is in `docs/bzr-cli.md`.
- **Avoid puff.** "creates a new bug under a product and component" beats "comprehensive bug creation workflow."

## 2. Inventory and scope

### 2.1 Manpage count vs. doc-comment count

| Layer | Files | Doc comments | Where they appear in manpages |
|---|---|---|---|
| Top-level `Cli` | `src/cli/mod.rs` | 1 struct + 7 global args | `bzr.1` DESCRIPTION + per-flag detail block |
| Subcommand groups | `src/cli/mod.rs` (`Commands` enum) | 14 variants | `bzr.1` SUBCOMMANDS list + each `bzr-<group>.1` DESCRIPTION |
| Action variants | each `*.rs` in `src/cli/` | 50 actions (see §2.2) | each `bzr-<group>-<action>.1` DESCRIPTION |
| Args / options | every `#[arg]`-bearing field | ≈140 fields | per-flag detail in the relevant manpage |

That covers all 66 generated pages.

### 2.2 Per-file inventory

| File | Actions | Args | Notes / structural duplication |
|---|---:|---:|---|
| `mod.rs` (Cli + Commands) | 14 groups | 7 globals | Globals already have decent shorts. Long bodies needed on `--server`, `--output`, `--json`, `--api`, `--verbose`. |
| `bug.rs` | 8 (List, View, Search, History, Create, My, Clone, Update) | 47 | Heaviest file. `--fields`/`--exclude-fields` recurs on List/View/Search/My — 4× duplication. Filter flags (`--product`, `--component`, `--status`, `--assignee`, `--creator`, `--priority`, `--severity`) recur on List, My, and `query.rs::Save` — 7 flags × 3 sites = 21 duplicates. |
| `comment.rs` | 4 (List, Add, Tag, SearchTags) | 7 | Self-contained. `add --body` needs the `$EDITOR` / stdin doc treatment. |
| `attachment.rs` | 4 (List, Download, Upload, Update) | 14 | `--flag` recurs on Upload + Update + bug Update — same syntax, document once and link. |
| `config.rs` | 6 (SetServer, SetDefault, Show, SetKeyring, UnsetKeyring, MigrateToKeyring) | 16 | `SetServer` has the most flags (12). TLS flags have non-trivial mutual exclusion that needs prose. |
| `product.rs` | 4 (List, View, Create, Update) | 8 | `--type` accepted values (`accessible`/`selectable`/`enterable`) need explicit enumeration. |
| `field.rs` | 2 (Aliases, List) | 1 | Smallest. `List` short already covers aliases — long body should give example aliases and link to bzr-cli(7). |
| `user.rs` | 3 (Search, Create, Update) | 9 | `Create --login` already has a long-ish doc that wraps awkwardly; restructure into short + long paragraphs. |
| `group.rs` | 6 (AddUser, RemoveUser, ListUsers, View, Create, Update) | 10 | Repeating `--group` and `--user` flags on Add/Remove/List can stay duplicated (they're each first-class action inputs). |
| `whoami.rs` | 1 (Show) | 0 | Tiny. `Cli::Whoami` parent doc and `Show` doc both need expansion. The parent has the special "no required subcommand" UX. |
| `server.rs` | 1 (Info) | 0 | Tiny. Long body should describe what's printed (version, extensions list). |
| `classification.rs` | 1 (View) | 1 | Tiny. Mention that classifications are a Bugzilla concept above products. |
| `component.rs` | 2 (Create, Update) | 7 | Self-contained. |
| `template.rs` | 4 (Save, List, Show, Delete) | 9 | Templates are local-only (no API call); long body should make that explicit and contrast with `query`. |
| `query.rs` | 5 (Save, List, Show, Delete, Run) | 16 | Mostly mirrors `bug list` filter flags. `Save --from-url` and `Run --server` have the most interesting semantics. |

**Totals:** 1 root + 14 group variants + 50 action variants + ~140 args = **205 doc comments**, of which roughly 60–70 args fall under "leave alone" per the §1.4 rubric. Net writing target ≈ 135–150 expanded comments.

### 2.3 Structural duplication — should we factor out shared `Args` structs?

**Recommendation: do not factor out for v0.2.0.**

Reasons:
1. The CLI surface is already shipped under `0.1.x`. A flatten-args refactor risks re-ordering options in `--help` and synopsis lines (clap orders args by struct field order, which would change). Manpage diffs would become large and noisy in a release that's supposed to be about content.
2. Each duplicate's prose is short enough (one sentence) that copy-paste discipline is cheaper than the refactor.
3. The `--flag` syntax doc (cf. `docs/bzr-cli.md` "Flag Syntax" section) is the only piece large enough to warrant DRY treatment — and even there, a one-line "see [Flag Syntax] in bzr-cli(7)" + a 2-line short doc is less risky than a shared struct.

A "shared prose snippets" alternative, if the duplication still bothers you in review: define `const`s like `FIELDS_HELP: &str` in a private module and reference them via `#[arg(long_help = FIELDS_HELP)]`. **Defer to a v0.3 cleanup.** Document the duplication explicitly in the v0.2.0 doc-expansion PR description so future maintainers know it's intentional.

## 3. Phasing

**Phase 1 — top-level + subcommand groups** (1 PR). 15 expansions: `Cli` + 14 `Commands` variants. Highest visibility, smallest count, fast feedback loop for groff/clap-mangen rendering corner cases (lists, examples, line breaks). Validate this phase end-to-end before scaling out.

**Phase 2 — action variants** (1 PR per file group). 50 expansions:
- 2a (heavy): `bug.rs`, `config.rs`, `query.rs` — most actions, most cross-references.
- 2b (medium): `attachment.rs`, `comment.rs`, `user.rs`, `group.rs`, `product.rs`, `template.rs`, `component.rs`.
- 2c (trivial): `whoami.rs`, `server.rs`, `classification.rs`, `field.rs` — bundle into one PR.

**Phase 3 — per-arg detail** (1 PR, possibly two). Touches roughly 70–80 args. Most are 2–4 lines added per arg. Defer the rubric-fail args to "leave alone" — don't pad short docs with filler.

**Phase 4 — optional polish** (skip if unneeded). Add `verbatim_doc_comment` only on commands/args whose phase-1/2 rendering review found list or table issues.

Total: 4–6 PRs. Phases 1 → 2 → 3 are strictly sequential; phase 4 is contingent.

## 4. Validation

### 4.1 Per-PR manual loop

```bash
make man                                   # regenerates man/man1/*.1
git diff --stat man/man1/                  # confirms only expected pages changed
groff -man -Tutf8 man/man1/bzr.1 | less    # eyeball the parent page
groff -man -Tutf8 man/man1/bzr-bug-create.1 | less
cargo run -- bug create --help             # confirm long-form help reads well in terminal
```

The CI Manpages job already runs `groff -man -Tutf8 *.1 > /dev/null` on every push, which catches roff syntax breakage. That's necessary but not sufficient — it doesn't catch "rendering looks bad," which only an eyeball pass on a representative sample finds.

### 4.2 Representative sample for human review

Render and read these pages (cover all rendering cases — short doc, long doc with examples, multi-paragraph, list, cross-reference):

- `bzr.1` (top-level)
- `bzr-bug.1` (parent with examples)
- `bzr-bug-create.1` (action with examples + exit codes)
- `bzr-bug-list.1` (action with many filter flags)
- `bzr-config-set-server.1` (action with mutually exclusive flags)
- `bzr-comment-add.1` (action with `$EDITOR` / stdin behavior)

If those six render cleanly, the rest are very likely fine.

### 4.3 Cross-reference against `docs/bzr-cli.md`

Run a structural cross-check before merging each PR:

1. Every example in a doc comment should appear (verbatim or near-verbatim) in `docs/bzr-cli.md` already, or be added there in the same PR.
2. Every `bzr-foo-bar(1)` cross-reference in a doc comment should point at a real page (i.e., a real `<group> <action>` pair).
3. Every flag mentioned in long-help prose should exist on that command (`grep` the flag name in the same `*.rs` file).

### 4.4 Structural lint

Add a test in `src/cli/mod.rs::tests` (phase 2a) that walks `<Cli as CommandFactory>::command()` recursively and asserts every leaf subcommand's `get_long_about()` is `Some` and differs from `get_about()`. clap exposes both via the `Command` API. ~30 lines of test code, no new deps. Don't add it in phase 1 — it would block partial progress.

A second linter idea — "every flag with `conflicts_with*` has a `long_help` mentioning the conflict" — is more precise but harder to implement and probably overkill. Skip.

### 4.5 No regressions on existing tests

`cargo test --locked` exercises 50+ parser tests in `src/cli/mod.rs::tests`. Doc-comment edits cannot break parsing, but a misspelled `#[command(...)]` attribute or accidental `verbatim_doc_comment` on a non-string would. Pre-push hook handles this.

## 5. Risks and open questions

### 5.1 Indented examples vs. clap's whitespace stripping

Clap-derive's default preprocessing collapses internal newlines within a paragraph but separates paragraphs at blank `///` lines. An indented example block separated above and below by blank `///` lines will be treated as its own paragraph, and clap-mangen renders it inside `.RS`/`.RE` indentation. Practical concern: example blocks like

```rust
/// Examples:
///
///     bzr bug create --product P --component C --summary "..."
///     bzr bug create --template t --summary "..."
```

may render as a single space-separated line in roff. **This is the one place we may need `verbatim_doc_comment`.** Add it on the parent `#[command]` attribute on every action variant whose long help contains an example block:

```rust
#[command(verbatim_doc_comment)]
Create { ... }
```

**Phase 1 task 1: write `Cli` doc, regenerate, render `bzr.1`, confirm whether examples render line-by-line.** If they do (clap_mangen 0.3 may handle indented paragraphs cleanly), drop the `verbatim_doc_comment` plan. If they don't, the rest of phase 2 needs the attribute on every action with examples (~50 sites).

### 5.2 List rendering

Bulleted prose lists ("`-` foo / `-` bar") inside doc comments don't get any special roff treatment from clap-mangen — they render as plain text with a literal `-` character. **Recommendation:** avoid Markdown-style bullet lists in doc comments. Use prose ("Mutually exclusive with `--tls-insecure`, `--tls-pin-sha256`, and `--tls-pin-now`") or a verbatim block when a list is unavoidable.

### 5.3 `--help` vs. man page divergence

The same doc comment must render acceptably in both. Most common failure mode: a doc that's tuned for man-page width feels too long in `--help`. Mitigation: keep the long body to 1–4 paragraphs per command. Anything longer probably belongs in `docs/bzr-cli.md`.

### 5.4 `bzr whoami` without subcommand

`Cli::Whoami { action: Option<WhoamiAction> }` allows `bzr whoami` with no `show` subcommand. The doc comment on `Commands::Whoami` should make this explicit: "Run with no subcommand or with `show` to print the authenticated user."

### 5.5 `clap_mangen` version

`xtask/Cargo.toml` pins `clap_mangen = "0.3"` (latest as of the cutoff). No upgrade is needed for this work.

### 5.6 Should `Cli` drop the `about = "A CLI for Bugzilla"` attribute?

Yes — once a doc comment is present on the `Cli` struct, the explicit `#[command(about = "...")]` becomes redundant and can shadow the doc. Remove it as part of phase 1. Sanity-check by running `cargo run -- --help` after the change and confirming the new wording appears.

## 6. Estimated effort

Roughly **8–12 hours of focused writing**, distributed:

| Phase | Hours | Output |
|---|---:|---|
| 1 — Cli + 14 groups | 1.5 | 1 PR, ~120-line diff, tests + groff render |
| 2a — bug + config + query | 3.0 | 1 PR, ~400 lines |
| 2b — medium files (7 files) | 3.0 | 1–2 PRs, ~350 lines total |
| 2c — trivial files (4 files) | 0.5 | 1 PR, ~80 lines |
| 3 — per-arg long-help expansion | 2.0 | 1 PR, ~300 lines |
| 4 — optional polish | 0.5 | 0–1 PR |

Add 10–15 minutes per PR for regenerating manpages and eyeballing the sample set. The structural lint test in phase 2a is ~30 minutes including review.

## 7. Recommendation / next steps

1. **Land phase 1 first as a proof-of-concept.** Confirm whether `verbatim_doc_comment` is needed for indented examples on the real `clap_mangen` 0.3 output.
2. **Lock the style guide (§1) into a short `docs/dev/cli-doc-style.md`** as part of the phase 1 PR so subsequent contributors don't have to rediscover the rules.
3. **Add the structural lint test in phase 2a** (after `bug.rs` is converted, so it has at least one full file to validate against).
4. **Treat `docs/bzr-cli.md` as the canonical content source.** When in doubt about wording, copy from there. Cross-link in both directions.
5. **Don't refactor recurring args into a shared struct for v0.2.0.** Document the duplication in the phase 2a PR description and revisit in v0.3.
6. **Skip `verbatim_doc_comment` until proven necessary** by phase 1 rendering review.

## Critical files for implementation

- `src/cli/mod.rs`
- `src/cli/bug.rs`
- `src/cli/config.rs`
- `src/cli/query.rs`
- `docs/bzr-cli.md`
