feat/introspect: opt-in second-level subcommand discovery for wraptool_discover #89

Merged
pti merged 1 commit from feat/introspect-second-level into main 2026-10-19 22:10:51 +02:00
Owner

Closes #51. A new per-tool setting introspection.discover_depth, default 1, makes wraptool_discover list second-level subcommands such as issue search when set to 2. Depth 2 probes each top-level command with the fixed help argv already used today, bounded by a strict lowercase name shape taken only from the parsed catalog, a skip-list for help and version and completion, a cap of 64 sorted groups and a 60 second budget per tool, second level only, no caller input in the argv. It is opt-in because a command that ignores -h runs for real with the tool's environment. The depth is folded into the introspection cache hash so toggling it re-introspects. The design question from the issue is settled in design/introspect/second-level-discovery.md, which also rejects default-on and an agent-steered drill-down argument. The description-loss investigation found no parser bug: fj prints bare command names without descriptions, and the parser did not recognise bare-name Commands blocks at all, so discover showed nothing for fj. The parser now reads a Commands block with optional descriptions and the urfave/cli alias form config, c, recording the primary name only. Fixtures from real fj -h, fj issue -h and jf --help output are in testdata with parser and end-to-end depth-2 tests, plus a regression test pinning every existing fixture's catalog. Reviewer pass done with argv-safety fuzzing and mutation checks. Docs in docs/configuration.qmd, CHANGELOG Added bullet, CLAUDE.md clause. 🤖 Generated with Claude Code

Closes #51. A new per-tool setting introspection.discover_depth, default 1, makes wraptool_discover list second-level subcommands such as issue search when set to 2. Depth 2 probes each top-level command with the fixed help argv already used today, bounded by a strict lowercase name shape taken only from the parsed catalog, a skip-list for help and version and completion, a cap of 64 sorted groups and a 60 second budget per tool, second level only, no caller input in the argv. It is opt-in because a command that ignores -h runs for real with the tool's environment. The depth is folded into the introspection cache hash so toggling it re-introspects. The design question from the issue is settled in design/introspect/second-level-discovery.md, which also rejects default-on and an agent-steered drill-down argument. The description-loss investigation found no parser bug: fj prints bare command names without descriptions, and the parser did not recognise bare-name Commands blocks at all, so discover showed nothing for fj. The parser now reads a Commands block with optional descriptions and the urfave/cli alias form config, c, recording the primary name only. Fixtures from real fj -h, fj issue -h and jf --help output are in testdata with parser and end-to-end depth-2 tests, plus a regression test pinning every existing fixture's catalog. Reviewer pass done with argv-safety fuzzing and mutation checks. Docs in docs/configuration.qmd, CHANGELOG Added bullet, CLAUDE.md clause. 🤖 Generated with Claude Code
feat(introspect): opt-in second-level subcommand discovery for wraptool_discover
All checks were successful
Lint / lint (pull_request) Successful in 58s
Lint / sonarqube (pull_request) Has been skipped
cb9c5dcae4
wraptool_discover served only the top-level catalog, so for a grouped CLI
such as fj the agent saw `issue` and `pr` but could not name `issue search`
in a capability request without guessing (#51).

A new per-tool option, introspection.discover_depth (1 or 2, default 1),
makes Introspect probe `<tool> <command> -h` for each top-level command and
merge the listed subcommands into Available as "command subcommand" keys.
It is opt-in because it runs commands no allow rule covers. Only names the
parser produced from the top-level help are probed, each must be a plain
lowercase command name, help/version/completion(s) are skipped, at most 32
groups are probed in sorted order, and no caller input reaches the argv.
Leaf commands, failed probes and non-help output contribute nothing and
never fail introspection. Available keeps its map shape, so the cache
format is unchanged; discover_depth 2 is folded into configHash so toggling
it regenerates the cache. The design note records the rejected
alternatives; the fj description-loss check awaits captured help output.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pti merged commit 79bb6dec6e into main 2026-10-19 22:10:51 +02:00
pti deleted branch feat/introspect-second-level 2026-10-19 22:10:51 +02:00
Sign in to join this conversation.
No reviewers
No labels
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
pti/wraptool!89
No description provided.