fix(help): render the page for the mount the words reached - #928
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
Greptile SummaryThe PR makes help rendering route-aware so shared subcommands mounted beneath multiple parents use the requested parent’s path and globals.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains. Important Files Changed
Reviews (4): Last reviewed commit: "fix(help): ask the parser which words na..." | Re-trigger Greptile |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b789fdf. Configure here.
`route_to` extended the route for a `help` word by scanning every token from where the parse stopped and skipping what did not match. A flag's detached value is just a word, so `ex --config alpha help beta shared` descended into `alpha` on the way past and printed `Usage: ex alpha shared` with alpha's globals — the mount bug this function exists to fix, reintroduced through a different door. It passed the arrival check because both mounts are one address, which is the thing that makes this hard to notice. Only the parser knows which tokens were in command position. It already resolves the words after `help` itself, one subcommand at a time, breaking at the first that names none — and then discarded the walk. It now records the `argv` range it covered, and `route_to` extends over exactly that, matching each word among the children of where it has got to. Two indices rather than the commands, so the parser goes on allocating nothing; empty for `--help`, which asks about wherever the parse reached. Tested in both directions, so a fix that merely preferred the later match would not pass, and mutation-checked: scanning raw argv again fails the new test with `Usage: ex alpha shared`. Reported by Greptile and Bugbot on #928.
|
Both of you were right, and I reproduced it before fixing: The arrival check did not catch it for the reason Bugbot gives: both mounts are one address, so Fixed in Tested in both directions — AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: unavailable. |
A `Subcommands` type mounted under two parents is one `Command` at one address, so `help::find` — which located a command by `core::ptr::eq` over the whole tree — returned whichever mount came first. `ex beta shared --help` printed `Usage: ex alpha shared`, with alpha's globals, for as long as this crate has had help. Diagnostics fixed their half of this by resolving the route rather than the command; help kept the pointer. A `&Command` cannot distinguish the mounts, so it cannot be the input. `route_to` builds the route from the argv the derive already has: it takes the path the parser walked, and for the `help beta shared` spelling — where the parse stops at the command that *saw* the word, short of the one being asked about — walks the remaining words by name among the children of wherever it has got to. By name, because the address is the thing that cannot be trusted here. `render_at` then resolves the metadata chain the same way, matching each step among that command's own children. `parse()` prefers the route and falls back to `render`, so a caller that reaches help by some other path still gets a page. Both spellings are tested, and so is the first mount — resolving by route must not make every page beta's.
`route_to` extended the route for a `help` word by scanning every token from where the parse stopped and skipping what did not match. A flag's detached value is just a word, so `ex --config alpha help beta shared` descended into `alpha` on the way past and printed `Usage: ex alpha shared` with alpha's globals — the mount bug this function exists to fix, reintroduced through a different door. It passed the arrival check because both mounts are one address, which is the thing that makes this hard to notice. Only the parser knows which tokens were in command position. It already resolves the words after `help` itself, one subcommand at a time, breaking at the first that names none — and then discarded the walk. It now records the `argv` range it covered, and `route_to` extends over exactly that, matching each word among the children of where it has got to. Two indices rather than the commands, so the parser goes on allocating nothing; empty for `--help`, which asks about wherever the parse reached. Tested in both directions, so a fix that merely preferred the later match would not pass, and mutation-checked: scanning raw argv again fails the new test with `Usage: ex alpha shared`. Reported by Greptile and Bugbot on #928.
Instruction counts
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 comparisonParsing
|

A
Subcommandstype mounted under two parents is oneCommandat oneaddress, so
help::find— which located a command bycore::ptr::eqoverthe whole tree — returned whichever mount came first.
ex beta shared --helpprintedUsage: ex alpha shared, with alpha's globals, for as longas this crate has had help. Diagnostics fixed their half of this by
resolving the route rather than the command; help kept the pointer.
A
&Commandcannot distinguish the mounts, so it cannot be the input.route_tobuilds the route from the argv the derive already has: it takesthe path the parser walked, and for the
help beta sharedspelling — wherethe parse stops at the command that saw the word, short of the one being
asked about — walks the remaining words by name among the children of
wherever it has got to. By name, because the address is the thing that
cannot be trusted here.
render_atthen resolves the metadata chain thesame way, matching each step among that command's own children.
parse()prefers the route and falls back torender, so a caller thatreaches help by some other path still gets a page.
Both spellings are tested, and so is the first mount — resolving by route
must not make every page beta's.
Stack created with GitHub Stacks CLI • Give Feedback 💬
Note
Medium Risk
Touches help rendering and generated
parse()exit paths; behavior change is intentional for shared mounts, with fallback preserving oldrenderwhen routing fails.Overview
Fixes wrong help for shared subcommands mounted under multiple parents. When the same
Subcommandstype is wired under two parents, both mounts share oneCommandpointer, sohelp::render/findpicked the first mount—e.g.ex beta shared --helpshowedUsage: ex alpha sharedand alpha’s globals.The parser records
help_span: theargvslice where thehelpword walked subcommand names (not flag values).help::route_tore-parses argv, builds the command path fromcommand_path+ that span, andhelp::render_atbuilds usage/metadata from that route by matching children per parent. Generatedparse()uses route +render_atonError::Help, falling back torenderwhen the route can’t be rebuilt.Conformance tests cover
--help,help beta shared, both mounts, and--config <name>so a global flag value isn’t mistaken for a route step.Reviewed by Cursor Bugbot for commit e00424a. Bugbot is set up for automated code reviews on this repo. Configure here.
AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: unavailable.