Repository navigation
docs(shell): correct who reads is_shell_integration_line - #4232
Conversation
The Usage list named uninstall, which has read is_shell_integration_line_for_uninstall_any_cmd since that function was introduced, and omitted install's idempotency check (contains_shell_integration) — the one caller where a false negative writes to a user-owned rc file instead of only choosing a message.
worktrunk-bot
left a comment
There was a problem hiding this comment.
wt config show is now named as one of the "messaging cases", but it isn't gated on the wrapper the way that section says. It calls scan_for_detection_details unconditionally and then emits Found <cmd> in <file:line> but not detected as integration: — and the bypass-alias warning after it — from loops with no shell_active guard (the if shell_active { … } else { … } block closes well above them). So "When wrapper is active: No warnings shown regardless of detection" is false for the caller this PR just added: a false negative there is a visible warning on every wt config show, including with integration working, not silence.
The wrapper gating is real, but it belongs to Shell::is_shell_configured()'s consumers in src/output/shell_integration.rs — should_show_explicit_path_hint and compute_shell_warning_reason, which run only off the not-active path. Scoping the exemption to that caller and giving wt config show its own line keeps the false-negative section true against the caller list the PR corrects; as written, the list and the analysis below it disagree about the same caller.
Pushing that edit to the branch.
wt config show scans on every run, so a false negative surfaces there as a 'found but not detected' warning whether or not the wrapper is active.
worktrunk-bot
left a comment
There was a problem hiding this comment.
The corrected Used by list still misses a caller, and it is one the new "install is the case that isn't benign" paragraph applies to.
contains_shell_integration is not install-private. It runs inside configure_shell_file, which scan_shell_configs drives for every shell, and scan_shell_configs has three callers: handle_configure_shell (install's preview and its apply), render_shell_status in src/commands/config/show.rs — so wt config show reads this function twice, once for its per-shell rows and once via scan_for_detection_details — and prompt_shell_integration in src/output/shell_integration.rs, the first-run offer wt switch makes when shell integration isn't active.
That third one carries the same cost the paragraph assigns to install alone. A false negative leaves current_shell_installed false, so wt switch offers to install integration on a machine that already has it; accepting calls apply_confirmed_shell_config, which is the same append. So the write is reachable from wt switch as well, and a later change reading this docstring would take wt config shell install to be the only path to it — the same shape of error this PR is correcting.
Pushing the edit: the bullet now names contains_shell_integration and its three readers rather than attributing it to install, and the false-negative paragraph names the wt switch route to the same write. RUSTDOCFLAGS='-Dwarnings' cargo doc --no-deps --document-private-items passes on it.
The Used by list attributed the idempotency check to `wt config shell install`, but `contains_shell_integration` runs under `scan_shell_configs`, which `wt config show` and `wt switch`'s first-run integration offer also drive. The offer reaches the same write: a false negative makes it offer an install the user already has, and accepting appends the duplicate line.
The
# Usageblock onis_shell_integration_linelists uninstall as a caller. Uninstall has not read it sinceis_shell_integration_line_for_uninstall_any_cmdwas introduced —scan_rc_file_for_uninstallandis_worktrunk_managed_contentboth call that one instead. The two docstrings now both claim the destructive path: the sibling's says "Used bywt config shell uninstall, which deletes the lines it matches. That makes a false positive destructive", which is the reasoning that should govern one function and not the other.The list also omits the caller that matters most for how carefully this function has to behave.
contains_shell_integration, install's idempotency check, is gated onis_shell_integration_lineat both call sites (configure_shell.rs, in the exists-check before the append and again inappend_shell_integration_if_missing). So the closing claim — "false negatives only cause incorrect messaging" — is wrong for install: a miss there reads an already-configured rc file as unconfigured and appends a second copy of the line to a user-owned file. Uninstall removes every line it matches, so the duplicate isn't stranded, but a write is a different cost from a wrong hint, and the docstring is what a later change to this function would be read against.The
# Impact of False Negativessection had a second inaccuracy of the same kind: it claimed detection is consulted only while shell integration is inactive, and that no warnings are shown once the wrapper is active. That holds forShell::is_shell_configured()'s consumers insrc/output/shell_integration.rs, which only ask off the not-active path, but not forwt config show— it callsscan_for_detection_detailsunconditionally and reports an unmatched line as a possible false negative regardless ofshell_active. The exemption is now scoped tois_shell_configured(), withwt config showdescribed on its own.So the rewrite lists the three real callers, says explicitly that uninstall is not one, and splits the false-negative analysis three ways: the gated messaging cases,
wt config show's ungated warning, and install's write.Comments only; no behavior changes, so there is nothing to regress-test.
RUSTDOCFLAGS='-Dwarnings' cargo doc --no-deps --document-private-items(the repo'sdocpre-merge step) passes, which is what checks the new intra-doc link.