Skip to content

refactor(setup): route bootstrap non-TTY guard through require_tty_or_yes - #70

Merged
tonythethompson merged 29 commits into
masterfrom
feature/require-tty-or-yes-bootstrap
Aug 3, 2026
Merged

refactor(setup): route bootstrap non-TTY guard through require_tty_or_yes#70
tonythethompson merged 29 commits into
masterfrom
feature/require-tty-or-yes-bootstrap

Conversation

@tonythethompson

@tonythethompson tonythethompson commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Symmetry-cleanup follow-up to PR #67 (feat: implement numan use for side-by-side Nu version management on feature/numan-use) and PR #69 (pr-migrate-legacy-installs).

Every destructive setup entry now flows through one require_tty_or_yes helper, with one audit pattern, in src/util/confirm.rs. Bootstrap's download/install path was the last surviving inline duplicate of the rule — this PR routes it through the helper so safe-batch automation can grep one consistent (audit) prefix across the whole setup surface instead of a mixed (audit) / Nushell setup cancelled. pair.

This PR must merge after PR #69 lands — the helper is already in feature/numan-use, but the other two destructive call sites it unifies live on pr-migrate-legacy-installs. Merging PR #67 first (i.e. this PR) would leave bootstrap as the only consumer and PR #69 would still be working against an old confirm.rs shape.

Three destructive-setup call sites (after this PR lands)

# Site Flow today After this PR
1 src/nu/bootstrap.rs::execute_nu_setup_with_installer (Nushell download + PATH mutation) inline if !options.yes && !std::io::stdin().is_terminal() { bail!("Nushell setup cancelled."); } crate::util::confirm::require_tty_or_yes(options.yes, "Nushell setup")?;
2 src/cmd/setup.rs::execute_use_existing / execute_use_path (off-path registration + managed-tree deletion) already calls require_tty_or_yes (PR #69 batch 1) unchanged
3 src/cmd/setup.rs::remove_managed_nu (numan setup nu remove destructive variant) already calls require_tty_or_yes (PR #69 batch 1) unchanged

Audit-text guaranteed identical: (audit) explicit --yes accepted for {what}; proceeding without interactive prompt. for the --yes path and (audit) implicit non-TTY session; refusing destructive {what} without --yes. for the non-TTY rejection path. The what labels are:

Diff stat (vs. feature/numan-use)

 src/nu/bootstrap.rs    | 39 +++++++++++++++++++++++++--------------
 tests/setup_nu_test.rs | 31 +++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 14 deletions(-)

Two commits on the branch:

SHA Title
63afdad refactor(setup): route bootstrap non-TTY guard through require_tty_or_yes
284772b refactor(setup): extract hoisted audit message helper + golden test

The second commit extracts pub fn hoisted_audit_message(parent: &Path) -> String in bootstrap.rs and pins its literal output via the new golden test tests/setup_nu_test.rs::register_existing_nu_audit_text_is_stable. Both require_tty_or_yes and hoisted_audit_message were already in feature/numan-use; this PR closes the bootstrap-side callers and locks the audit text so a future copy-edit can't surface four divergent variants.

Validation log

Gate Result
cargo build
cargo fmt --check
cargo clippy -- -D warnings
cargo test --lib 448 passed; 0 failed
cargo test --test setup_nu_test 17 passed; 0 failed (including new register_existing_nu_audit_text_is_stable)
Full cargo test --tests ✅ 16 test binaries, 0 failures, 7 ignored (real-Nu suite only runs in -- --ignored CI acceptance job)

Merge order

Gate: merge PR #69 first, then this PR.

If the gate is respected, the merge sequence is:

  1. PR [phase-1] cleanup: journaled legacy migration #69feature/numan-use (introduces the two require_tty_or_yes callers in cmd/setup.rs)
  2. This PR → feature/numan-use (closes the third caller in bootstrap.rs)
  3. feature/numan-usemaster (the eventual feature delivery)

Breaking the gate is recoverable but messy: PR #69 would re-introduce a divergent inline audit pattern in the meantime and require a follow-up rebase. The two PRs do not conflict on bootstrap.rs but they do conflict on the audit-trail contract.

Refs

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

Review in cubic

tonythethompson and others added 25 commits July 31, 2026 22:20
…nfirm utility

Breaking change: --remove, --use-path, --use-existing are replaced by subcommands (remove, path, use <path>). Hidden backward-compat flags emit deprecation warnings (remove in v0.3.0).

- Add src/util/confirm.rs: confirm_or_auto / confirm_or_bail (non-TTY auto-confirms)

- Replace 16 inline TTY-check sites across 8 files

- Normalize all --yes help text to 'Skip confirmation prompts'

- Redesign NuSetupArgs with Option<NuAction> subcommand + positional VERSION

- Add NuSetupArgs constructors for internal callers (doctor, nu_pin_offer)

- Add 8 CLI-parse tests + update all affected test assertions

- Update README, CHANGELOG, docs/numan-doctor.md, AGENTS.md
- Prevent PATH subcommand from deleting active managed Nu
- Guard loader overwrites with ownership verification
- Reject incompatible legacy Nu setup flags
Fix remaining --version references in resolve.rs, tighten doctor_test assertion, add skip_path guard to legacy compat path, add negative tests for version+subcommand and legacy use_existing+skip_path.
Change 'your PATH Nu is not touched' to 'your existing Nu is not replaced' since setup nu does modify PATH by default.
Introduce a new `numan use <version>` command path (`cli`, `main`, and `cmd::use_cmd`) as a post-1.0 placeholder that currently fails with a clear guidance message to use `numan setup nu <version>`. Update roadmap/docs to reflect the consolidated plan filename, add post-1.0 side-by-side Nu management notes, and register the new command module in AGENTS metadata.
Fixed 4 file(s) based on 5 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
- Add src/nu/version_manager.rs for active version tracking
  - Active version stored in <root>/nu_state/active-version.json
  - Installed versions discovered from <root>/tools/nushell/<version>/
  - Helpers: read/write active version, list installed, check if installed
  - Migration logic for legacy single-binary installs

- Update bootstrap.rs to install to versioned subdirectories
  - install_from_archive() now writes to <root>/tools/nushell/<version>/
  - managed_nu_binary() delegates to version_manager for active version
  - Automatically sets newly installed version as active

- Implement numan use command
  - numan use <version> — switch to specific installed version
  - numan use latest — switch to newest installed version
  - numan use list — show all installed versions with active marker
  - Validates version is installed before switching
  - Provides helpful hints when version not found
  - Auto-migrates legacy single-binary installs on first run

- Remove Commands::Use from root init exclusion (now needs root)

All 425 tests pass, clippy clean, fmt applied.
- Validate and normalize Nu versions
- Propagate legacy migration errors
- Handle invalid active markers gracefully
- Avoid parent path panic
- Update Nu setup guidance
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
…master for setup.rs, snapshot.rs, cli.rs, bootstrap.rs; keep full use_cmd.rs implementation
wip: puts numan use + confirm-gate UX + migration journal + reconcile
into a single baseline commit so the pr-migrate-legacy-installs split can
branch off a known starting point. This commit does not represent either
final PR; the next step surgically extracts migration into its own branch
and reverts the migration hunks on feature/numan-use.
- Drop state/migration-journal.rs (moves to pr-migrate-legacy-installs).
- Drop journal.migration_pending finding + reconcile block from cmd/doctor.rs.
- Drop CMD_USE constant from util/hints.rs (fix-hint for the migration
  journal finding; the constant is migration-specific).
- Drop pub mod migration_journal; from state/mod.rs.
- Drop migrate_legacy_install call from cmd/use_cmd.rs (will be re-added
  on the migration branch once it ships -- use_cmd.rs keeps the snapshot
  + active-marker write).
- Drop the migration_journal architectural bullet from AGENTS.md; keep
  the active-marker bullet (numan-use specific).
- Pull version_manager.rs from pr-migrate-legacy-installs (already
  numan-use only).
- The roadmap never had migration wording.

Result: feature/numan-use is pure numan-use feature (PR 67).
Migration pieces live on pr-migrate-legacy-installs.

Co-authored-by: Codebuff <noreply@codebuff.com>
…e-existing)

- Add validate_version_for_path in version_manager.rs: explicit
  entry point that rejects traversal / separators / non-semver so
  install paths can opt in to validating a caller-supplied version
  before joining it into the managed tree (CodeRabbit Critical
  finding: 'Validate the version string before you join it into a path').
  Keeps version_install_dir / version_binary returning PathBuf for
  call-site ergonomics; callers handling untrusted input call
  validate_version_for_path (or normalize_version) first.
- setup.rs hard-coded the removed '--use-existing' flag in a println
  message. Drop the flag reference; the message now describes the
  replacement ('replaced by user-supplied Nu') and matches the prompt
  Greptile suggested.

CI: build + fmt + clippy -- -D warnings clean; 442 tests pass.
The unresolved PR 67 review finding (PRRT_kwDOTGvfHs6VpJrb) asks
install_from_archive to place binaries under
<root>/tools/nushell/<version>/nu rather than the legacy single-binary
<root>/tools/nushell/nu. That keeps install a pure payload write and
keeps active-marker persistence owned by execute_nu_setup_with_installer,
matching AGENTS.md's 'only activate/deactivate modify Nu integration
state' invariant.

The companion unit test now asserts against
version_manager::version_binary(root, "0.0.0-test") so a regression to
the flat layout would fail loudly instead of silently clobbering every
installed version on the next install.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
PRRT_kwDOTGvfHs6VpJrf (CLAUDE.md)
  Drop the mandatory model-specific Co-Authored-By trailer; require
  explicit user request before adding any attribution. HEREDOC guidance
  preserved.

PRRT_kwDOTGvfHs6VpJrm (docs)
  README.md: add numan use <version>/latest/list rows + common-flags row.
  AGENTS.md: replace 'reserved stub' with current implemented behavior.
  CHANGELOG.md: Unreleased Added section now covers numan use, versioned
  install layout, strict version-path validation.

PRRT_kwDOTGvfHs6VpJrq (test seam)
  src/util/confirm.rs gains confirm_or_auto_with_tty / require_tty_or_yes_with_tty
  variants that let tests assert both branches unconditionally. activate.rs,
  deactivate.rs and tests/activate_test.rs drop their is_terminal guards and
  use the new variants directly. Three new unit tests cover the non-TTY bail,
  non-TTY auto-confirm, and --yes-polarity paths.

PRRT_kwDOTGvfHs6VpJrv (doctor lock)
  setup::execute_nu_repair acquires the mutation lock before delegating to
  execute_nu_impl; doctor.rs both repair branches route through it. AGENTS.md
  'Every mutating code path must acquire the mutation lock' invariant restored.

PRRT_kwDOTGvfHs6VpJrx (dedup)
  The duplicated --skip-path reject message (legacy flag path + subcommand
  path) collapses into reject_skip_path_for_off_path_registration so the two
  branches can't drift apart.

PRRT_kwDOTGvfHs6VpJsA (loader marker)
  Verified that assets/nushell-loader/loader.nu's first two lines already
  match OWNERSHIP_MARKER ('# Generated and managed by Numan. Do not edit.'
  + '# Numan autoload schema: 1'). Existing setup.rs install flow's
  VENDOR_LOADER write propagates the marker; assert_managed_file_owned will
  no longer trip on overwrite. No code change required.

PRRT_kwDOTGvfHs6VpJsF (try help)
  TryArgs.yes doc comment now explicitly calls out the managed-Nu pin
  refusal boundary: --yes does NOT consent to silent managed-Nu install
  or version switch.

PRRT_kwDOTGvfHs6VpJsS (resolve doc)
  append_nu_mismatch_remediation doc comment corrected: PATH-touched-ness
  is removed (setup nu may persist PATH unless --skip-path); messages
  actually say 'your existing Nu is not replaced' and end with the
  per-Nu-activation note.

Validation: cargo build / cargo fmt --check / cargo clippy -- -D warnings /
cargo test --lib (445 passed; 0 failed) / cargo test --test activate_test
(18 passed; 0 failed) on Windows toolchain.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
…up_nu_test refactor

Addresses final 4 newly-surfaced PR 67 review threads:

PRRT_kwDOTGvfHs6VpJss (Critical)
  Add an explicit ConfirmPolicy enum (AutoConfirm vs RefuseOnNonTTY) and
  a unified confirm_or_auto_with helper. Callers needing the refusing
  variant (destructive ops) pass it explicitly; idempotent setup callers
  keep auto-confirm-on-non-TTY. Default  still auto-
  confirms, matching CI/script idempotency expectations.

PRRT_kwDOTGvfHs6VpJst
  confirm.rs mod tests now exercises non-TTY bail, AutoConfirm policy
  pass-through, and yes-polarity short-circuit. Three new tests cover
  the branches that previously only ran via is_terminal-dependent
  paths.

PRRT_kwDOTGvfHs6VpJsu
  hints.rs gains shell_quote(s) and uses it inside setup_nu_use_existing.
  Fix hints pointing at paths with spaces or shell metacharacters now
  copy-paste into a POSIX-ish shell.

PRRT_kwDOTGvfHs6VpJsv
  Add NuSetupArgs::use_existing_for_test(path, skip_path, yes) and use
  it in tests/setup_nu_test.rs. Hand-listing eight struct fields
  silently drifts when fields are added. The constructor name
  (_for_test) signals intent; it is unconditional  because
  integration tests build the lib without cfg(test).

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Adds scripts/check-roadmap-drift.py to detect the same kind of drift PR
67 hit: shipped-feature bullets whose wording still calls them 'stub',
'reserved', or 'post-1.0 reserved'. The check passes when the consolidated
roadmap is consistent with what code actually ships, and exits 1 otherwise.

Rules:
  * The consolidated roadmap must declare the repo-local roadmap rule and
    name numan-plugins/docs/roadmap.md and numan-registry/docs/roadmap.md
    so future maintainers in either sibling repo know where cross-repo
    truth lives.
  * No bullet outside a deferral/post-1.0/explicitly-deferred heading may
    contain 'stub', 'reserved', 'post-1.0 reserved', 'exists as a stub',
    or 'is a reserved'. Bullets are 'shipped-feel' when they carry an
    [x] checkbox, a 'Wave N closed' / 'Phase N (shipped)' marker, or a
    `numan <verb>` / `scripts/<name>.py` command pattern.
  * If docs/roadmap.md exists in a repo, it must link back to the
    consolidated roadmap; missing local roadmap becomes a warning (so the
    source-of-truth repo  doesn't fail), not an error.

A negative test (inject the PR67 'exists as a stub in 0.1.x / post-1.0
reserved' bullet) fails the check with four matches; the pristine
roadmap succeeds.

Mirror this script + the same 'roadmap-drift' job into numan-plugins
and numan-registry with CONSOLIDATED_ROADMAP=/LOCAL_ROADMAP= env overrides
pointing at each repo's local roadmap.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Catches the next stale roadmap claim before it misleads downstream
planning in numan-plugins or numan-registry. Each bullet in the
"Side-by-side Nu version management (numan use)" section is now either
backed by src/ code with a file:line pointer or visibly tagged as
"Vision only — not yet shipped."

Specific corrections (cross-repo claim → shipped behavior):

  * "numan use list ... + per-version plugin counts" → drop the
    inaccurate half; execute_list (src/cmd/use_cmd.rs) currently prints
    version + (active) only. Counts are forward-looking.

  * "PATH/shim: Numan does not manage a shim." → CONTRADICTION.
    persist_user_path_unix (src/nu/bootstrap.rs:561) creates a
    ~/.local/bin/nu symlink via std::os::unix::fs::symlink on Unix;
    on Windows it appends the binary's parent to the user PATH. The
    bullet is rewritten into three accurate bullets: PATH (Unix) /
    PATH (process-only) / Active marker ownership, each citing the
    concrete call site.

  * "Lockfile plugin_activation becomes keyed by Nu version" → partial.
    Each PluginActivation already carries nu_version: String
    (src/state/lockfile.rs:44); the "Switching activates/deactivates
    automatically" companion claim is aspirational. Split into one
    SHIPPED bullet and three Vision-only aspirational bullets so the
    shipped structure stays separated from the future behavior.

  * All three "Numan-level aliases (optional)" bullets → Vision only.
    No numan alias command exists in src/cli.rs; tag each.

  * Catalog implication + "Use this to drive backfill waves once
    numan use ships" → Vision-tag the forward-looking clauses; keep
    the verifiable cross-repo fact about numan-plugins/docs/backlog.json
    schema v1 (verified outside this repo).

The check-roadmap-drift.py script still passes on the post-audit
roadmap (0 errors, 1 warning for the absent repo-local roadmap,
expected for numan). A re-run of the negative PR67 contradiction
injection still exits 1 with four forbidden-phrase matches, so the
guardrail survives the audit.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Closes the third leg of the cross-repo compliance rail: PR 67's roadmap
drift shipped in numan/scripts, but a guard only one side knows about
isn't a guardrail. This commit lays down drop-in artifacts the sibling
repos can paste-and-PR so the drift check fires on both sides too.

Artifacts (under cross-repo-mirror/):
  * numan-plugins/docs/roadmap.md        — thin pointer back to consolidated
  * numan-plugins/.github/workflows/roadmap-drift.yml — CI job, fetches
    the consolidated roadmap from numan@master and runs
    scripts/check-roadmap-drift.py against it; same shape for registry.
  * numan-registry/docs/roadmap.md        — same shape, registry-side.
  * numan-registry/.github/workflows/roadmap-drift.yml
  * snapshot-tests/mirror_dry_run.sh     — local sanity check that
    both sibling CI jobs would pass against the current state of the
    script and the consolidated roadmap. ALL MIRRORS PASS (= 0 errors,
    0 warnings) for both numan-plugins and numan-registry.
  * README.md                            — explains the mirror contract
    and the install instructions for the maintainer of the sibling
    repos.

Mechanics:
  * The CI workflows curl the consolidated roadmap straight from
    numan@master each run — the sibling repo never holds a stale copy.
    The fetch step greps for the sibling's repo-local roadmap path; if
    the canonical doc ever forgets to mention a sibling, that sibling's
    drift job fails loudly instead of degrading silently.
  * The script is pulled from numan@master the same way. Both pinned
    via standard GitHub raw URL with --fail-with-body so a downgrade
    triggers a visible error rather than a soft pass.
  * Defense in depth: a second grep step repeats the repo-local cross-
    link check directly in case the script's logic ever regresses.

Script polish:
  * scripts/check-roadmap-drift.py honours --help / -h before treating
    argv[1] as a path; prints the module docstring and exits 0. CI
    invocations and human invocations both stop crashing on stray --help.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Copilot AI review requested due to automatic review settings August 2, 2026 12:15
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@tonythethompson, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 001c9beb-f1d4-4de0-8358-eb50d6f73387

📥 Commits

Reviewing files that changed from the base of the PR and between 7b702b1 and ffbddcc.

📒 Files selected for processing (1)
  • src/nu/bootstrap.rs
📝 Walkthrough

Walkthrough

Nushell bootstrap now exposes a shared hoisted-consent audit formatter and requires an interactive terminal or explicit --yes before setup or managed Nushell removal proceeds. Tests cover TTY overrides, refusal behavior, and exact audit output.

Changes

Nushell setup consent

Layer / File(s) Summary
Hoisted audit message integration
src/util/confirm.rs, src/nu/bootstrap.rs, tests/setup_nu_test.rs
Adds and re-exports hoisted_audit_message, uses it for hoisted-consent audit output, and tests normal and empty parent paths.
Interactive setup confirmation gate
src/nu/bootstrap.rs, src/cmd/setup.rs
Adds NuSetupOptions.is_tty, enforces TTY or --yes for setup and managed Nushell removal, and verifies refusal before installation.
Setup option initialization
src/cmd/setup.rs, src/nu/bootstrap.rs, tests/setup_nu_test.rs
Initializes is_tty as None across setup, registration, and test fixtures.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: cursoragent

🚥 Pre-merge checks | ✅ 8
✅ Passed checks (8 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main setup refactor: routing the bootstrap non-TTY guard through require_tty_or_yes.
Description check ✅ Passed The description directly explains the helper refactor, audit-message standardization, tests, validation, and merge-order requirement.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Pipeline Stage Enum Ordering ✅ Passed The repository and PR changes contain no SessionWorkflowStage enum or member references, so pipeline ordering, raw-literal, renumbering, and inequality checks are not applicable.
Gpu/Cpu Runtime Boundary ✅ Passed The diff changes only Rust, Python, and test files; no inference/ directory, CPU/GPU requirements file, or C# diarization code is modified, so the boundary rules are not triggered.
Managed Host Restart Safety ✅ Passed The PR changes only Nushell setup and confirmation code; none of the four managed-host components or host restart/readiness methods exist or are modified.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/require-tty-or-yes-bootstrap
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feature/require-tty-or-yes-bootstrap

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

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Refactor setup bootstrap non-TTY guard through require_tty_or_yes

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Route bootstrap non-TTY destructive guard through require_tty_or_yes for consistent audit
 output.
• Extract a shared hoisted-consent audit message helper for PATH registration.
• Add golden tests to pin (audit) text relied on by batch automation.
Diagram

graph TD
  A["bootstrap.rs: execute_nu_setup_with_installer"] --> B["confirm.rs: require_tty_or_yes"] --> C["confirm.rs: confirm_or_bail"]
  D["bootstrap.rs: register_existing_nu"] --> E["bootstrap.rs: hoisted_audit_message"] --> F["tests/setup_nu_test.rs"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Structured audit events (stable IDs) instead of grep-able strings
  • ➕ Eliminates brittleness around punctuation/spacing changes
  • ➕ Supports future machine parsing without golden-string tests
  • ➕ Allows localization/user-facing text changes independently of automation
  • ➖ Requires introducing an event schema and updating consumers
  • ➖ More invasive than this PR’s targeted cleanup
2. Centralize all audit text in a single confirm/audit module
  • ➕ Keeps the current grep-based contract but reduces string duplication further
  • ➕ Improves discoverability of automation-relevant messages
  • ➖ May over-centralize messages that are context-specific to bootstrap/setup
3. Use a logging framework with key=value fields for audit lines
  • ➕ More consistent formatting and routing (stderr/stdout) across commands
  • ➕ Can include structured fields like action, what, decision, tty
  • ➖ Adds dependency/configuration complexity
  • ➖ Still requires downstream conventions to stay stable

Recommendation: The PR’s approach is the right incremental step: it removes the last inline non-TTY destructive guard and funnels behavior through one helper, making audit output uniform across setup entry points. The added golden test is appropriate given the current grep-based contract; consider evolving to structured audit event IDs later if automation needs grow or message churn becomes painful.

Files changed (2) +56 / -14

Refactor (1) +25 / -14
bootstrap.rsUnify non-TTY destructive gating and extract hoisted audit formatter +25/-14

Unify non-TTY destructive gating and extract hoisted audit formatter

• Replaces the inline non-TTY guard in the download/install setup path with 'crate::util::confirm::require_tty_or_yes(...)' to standardize audit-grade behavior and messaging. Extracts 'hoisted_audit_message(parent)' and uses it in the hoisted-consent branch to prevent silent text drift; includes minor formatting cleanup for version normalization error context.

src/nu/bootstrap.rs

Tests (1) +31 / -0
setup_nu_test.rsAdd golden test for hoisted-consent audit message stability +31/-0

Add golden test for hoisted-consent audit message stability

• Adds a test that asserts the exact '(audit)' string produced by 'hoisted_audit_message', including an empty-path corner case. This pins stderr output relied on by safe-batch automation that greps for audit decisions.

tests/setup_nu_test.rs

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Since hoisted_audit_message is meant to be reused by multiple destructive flows, consider moving it out of nu::bootstrap into a shared audit/confirm module so future callers don’t have to depend on bootstrap-specific code.
  • Relying on exact (audit) strings for automation grep is quite brittle; you might want to introduce a small structured audit/logging helper (e.g., fixed tokens or fields around the prose) so the machine-readable contract is stable even if the human-facing text is later copy-edited.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Since `hoisted_audit_message` is meant to be reused by multiple destructive flows, consider moving it out of `nu::bootstrap` into a shared audit/confirm module so future callers don’t have to depend on bootstrap-specific code.
- Relying on exact `(audit)` strings for automation grep is quite brittle; you might want to introduce a small structured audit/logging helper (e.g., fixed tokens or fields around the prose) so the machine-readable contract is stable even if the human-facing text is later copy-edited.

Fix all in Cursor


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the Nushell bootstrap/setup flow so the non-interactive (“non-TTY”) destructive-operation guard is consistently enforced via util::confirm::require_tty_or_yes, aligning bootstrap with the rest of the setup surface’s audit/log contract.

Changes:

  • Route src/nu/bootstrap.rs non-TTY destructive guard through require_tty_or_yes for consistent audit output and behavior.
  • Extract a shared hoisted_audit_message() formatter used by the hoisted-consent branch.
  • Add a golden-string test to pin the audit message text.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/nu/bootstrap.rs Replaces the inline non-TTY guard with require_tty_or_yes and factors audit text into hoisted_audit_message().
tests/setup_nu_test.rs Adds a golden test to pin the audit-trail message emitted when consent prompting is hoisted.

Comment thread tests/setup_nu_test.rs Outdated
@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR is a symmetry cleanup that routes bootstrap.rs's last inline non-TTY guard through the shared require_tty_or_yes_with_tty helper in confirm.rs, unifying all three destructive setup entry points under one audit pattern. It also extracts hoisted_audit_message into confirm.rs and pins its literal output with a golden test.

  • src/nu/bootstrap.rs: replaces the inline if !options.yes && !stdin().is_terminal() { bail!(...) } guard in execute_nu_setup_with_installer and the register_existing_nu branch with require_tty_or_yes_with_tty; adds is_tty: Option<bool> to NuSetupOptions for test injection; adds two unit tests covering the non-TTY refusal path.
  • src/util/confirm.rs: adds hoisted_audit_message with a unit test; src/cmd/setup.rs gains a require_tty_or_yes guard before remove_managed_nu's confirm_or_bail call.
  • scripts/apply_install_from_archive_fix.py: new one-shot patcher committed alongside the changes it describes — it would fail if re-run against the current codebase.

Confidence Score: 5/5

Safe to merge once the merge-order gate (PR #69 first) is respected; the refactoring is narrow and well-tested.

The core logic change — replacing an inline TTY check with the shared helper — is straightforward and covered by new unit tests that verify both the refusal path and PATH immutability. The confirm_or_bail call in remove_managed_nu correctly threads the yes variable, so the double-prompt concern does not apply. The only flag is the committed one-shot Python patcher in scripts/, which is already stale but has no runtime impact.

Files Needing Attention: scripts/apply_install_from_archive_fix.py — one-shot patcher committed after its target changes are already applied; not a runtime concern but may confuse future maintainers

Important Files Changed

Filename Overview
scripts/apply_install_from_archive_fix.py One-shot patcher committed after its changes are already applied; fails with AssertionError if re-run
src/nu/bootstrap.rs Routes non-TTY guard through require_tty_or_yes_with_tty, adds is_tty injection hook, and adds two tests covering the refusal path
src/util/confirm.rs Adds hoisted_audit_message helper with a unit test; clean addition with golden test coverage
src/cmd/setup.rs Adds require_tty_or_yes guard before remove_managed_nu's confirm_or_bail and populates new is_tty: None fields; yes parameter is correctly threaded through
tests/setup_nu_test.rs Adds golden-string stability test for the hoisted audit message and updates struct initializers for the new is_tty field

Reviews (4): Last reviewed commit: "fix(setup): gate register_existing_nu be..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/setup_nu_test.rs`:
- Around line 271-300: Add bootstrap-level coverage around
execute_nu_setup_with_installer for non-TTY input: introduce an injectable
TTY-detection seam, invoke the setup with yes=false and a simulated non-TTY, and
assert the installer is not called. Keep the existing
require_tty_or_yes_with_tty behavior and --yes coverage unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 89b51d0d-717e-46de-9a17-08031619d704

📥 Commits

Reviewing files that changed from the base of the PR and between 99aa695 and 284772b.

📒 Files selected for processing (2)
  • src/nu/bootstrap.rs
  • tests/setup_nu_test.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Trackdubllc/Trackdub (manual)
  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: copilot-pull-request-reviewer
  • GitHub Check: Greptile Review
  • GitHub Check: Sourcery review
🧰 Additional context used
📓 Path-based instructions (6)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Use anyhow::Result with .context("what failed") for application code, thiserror for library types callers match on, and avoid panics in library code by returning Result.

**/*.rs: Use Rust 2021 edition conventions and match existing naming, module layout, and documentation level in edited files.
Use anyhow::Result with .context(...) in application code; use thiserror for library error types that callers match on.
Use clap derive macros for CLI definitions.
Use serde with serde_json or toml for serialization.
Function parameters must use &Path, not &PathBuf.
Error paths must return anyhow::Result with context, and library code must not panic.
Unit tests must use injectable seams such as FakeCandidateRunner and registrars; do not spawn real nu in unit tests.
Real-Nu acceptance tests should be marked #[ignore] and run separately when activation or nupm-import behavior changes.
Every new mutating code path must acquire the mutation lock and snapshot the lockfile before writes.
Mutating commands, including install, remove, update, gc, and nupm import, must call acquire_mutation_lock(root).
Lockfiles, journals, and state files must be written atomically using write_json_atomic.
numan install must write only to $NUMAN_ROOT and must not invoke Nu or register plugins/autoloads.
Only activate and deactivate may modify Nu integration state.
Treat the lockfile as the authoritative source of truth; derived projections such as autoload state are not authoritative.
Install payloads must use versioned, content-addressed paths and must never be overwritten in place.
Never overwrite foreign autoload files; respect OWNERSHIP_MARKER.
Pass plugin paths through environment variables only; do not use runtime interpolation in Nu program strings.
The nupm boundary must remain read-only toward NUPM_HOME, must not execute build.nu, and must not perform bidirectional synchronization.

Use Rust 2021 conventions; the crate's MSRV is...

Files:

  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,toml}: All changes must pass formatting and linting: cargo fmt and cargo clippy -- -D warnings.
Behavior changes require corresponding tests, including relevant failure paths.

Files:

  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.{rs,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update documentation when changing structure, conventions, or user-visible behavior, using AGENTS.md, docs/, or command help as appropriate.

Files:

  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Redact secrets when reporting relevant logs or lockfile excerpts in issues.

Files:

  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.rs: Keep unit tests inline with source modules and integration tests under tests/; test platform-specific code with mock platforms.
Real-Nu acceptance tests may be ignored and must be run with cargo test -- --ignored; unit tests should use injected fakes rather than a real Nu process.

Files:

  • tests/setup_nu_test.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.rs: Use anyhow::Result for application code and thiserror for library errors; add error context with .context(...) or ?, and never panic in library code.
Use &Path rather than &PathBuf in function parameters.

Files:

  • src/nu/bootstrap.rs
🔍 Remote MCP GitHub Copilot

Relevant review context

  • PR #70 is open with two commits: 63afdad updates the bootstrap guard; 284772b extracts hoisted_audit_message and adds the golden test.
  • The shared helper inherited from feature/numan-use has distinct behavior: explicit --yes proceeds with an audit line, non-TTY without --yes fails, and interactive TTY proceeds to the normal prompt. Both branches have injectable tests.
  • Bootstrap now calls require_tty_or_yes(options.yes, "Nushell setup") before confirm_or_bail, preventing piped downloads without --yes while retaining the interactive prompt.
  • The formatter’s exact output is covered for /usr/local/bin and an empty path.
  • PR #69 remains open and blocked; PR #70’s description requires PR #69 to merge first because the setup call sites are intentionally stacked.
  • PR #70 currently has no submitted reviews or review threads; all four automated review checks are still in progress.
🔇 Additional comments (3)
src/nu/bootstrap.rs (3)

222-223: LGTM!


443-458: LGTM!

Also applies to: 485-485


735-740: LGTM!

Comment thread tests/setup_nu_test.rs

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 284772baad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/nu/bootstrap.rs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 2 files

Shadow auto-approve: would auto-approve. Refactor routes an existing non-TTY guard through the shared require_tty_or_yes helper and adds a golden test for the hoisted audit message. The change is focused, behavior-preserving cleanup with no expansion of exposure or new operational tradeoffs.

Re-trigger cubic

Keep master's numan use / off-tree / install-active PATH behavior, PR 70's
require_tty_or_yes bootstrap download guard and hoisted_audit_message.
Route managed Nu removal through require_tty_or_yes, add an is_tty test
seam with non-TTY installer refusal coverage, and make the audit golden
test path-display portable.

Co-authored-by: Anthony Thompson <github@trackdub.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/nu/bootstrap.rs (1)

732-745: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Establish the required mutation transaction before setup state changes.

These paths mutate PATH, active-version state, or the managed Nushell tree without a visible mutation lock and snapshot before the first write. Concurrent setup, removal, or replacement can interleave and leave the active marker or managed payload state inconsistent.

  • src/nu/bootstrap.rs#L732-L745: acquire the mutation lock and create the snapshot before the --yes already-installed PATH update.
  • src/nu/bootstrap.rs#L811-L827: retain the mutation lock through active-version persistence and persistent PATH updates.
  • src/cmd/setup.rs#L461-L463: acquire the mutation lock and create the snapshot before clearing the active-version marker.
  • src/cmd/setup.rs#L482-L487: acquire the same lock and snapshot before replacement clears state and deletes the managed tree.

As per coding guidelines, “Every new mutating code path must acquire the mutation lock and snapshot the lockfile before writes.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/nu/bootstrap.rs` around lines 732 - 745, Establish the mutation
transaction before every listed write: in src/nu/bootstrap.rs lines 732-745,
acquire the mutation lock and snapshot the lockfile before the --yes
already-installed PATH updates; in src/nu/bootstrap.rs lines 811-827, retain
that lock through active-version persistence and persistent PATH updates; in
src/cmd/setup.rs lines 461-463, acquire the lock and snapshot before clearing
the active-version marker; and in src/cmd/setup.rs lines 482-487, do the same
before replacement clears state or deletes the managed tree. Use the existing
mutation-lock and snapshot mechanisms consistently across all four sites.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/nu/bootstrap.rs`:
- Around line 486-490: Update register_existing_nu so that when
caller_consented_destructive is false, it invokes the TTY gate using
options.is_tty before confirm_or_bail, rejecting non-TTY execution unless
explicitly approved; preserve the existing confirmation flow for interactive
callers and ensure PATH mutation and active-version updates occur only after
this gate.

---

Outside diff comments:
In `@src/nu/bootstrap.rs`:
- Around line 732-745: Establish the mutation transaction before every listed
write: in src/nu/bootstrap.rs lines 732-745, acquire the mutation lock and
snapshot the lockfile before the --yes already-installed PATH updates; in
src/nu/bootstrap.rs lines 811-827, retain that lock through active-version
persistence and persistent PATH updates; in src/cmd/setup.rs lines 461-463,
acquire the lock and snapshot before clearing the active-version marker; and in
src/cmd/setup.rs lines 482-487, do the same before replacement clears state or
deletes the managed tree. Use the existing mutation-lock and snapshot mechanisms
consistently across all four sites.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: db6f00a5-9ed0-469a-92c8-43664578bcc0

📥 Commits

Reviewing files that changed from the base of the PR and between 284772b and b2d156c.

📒 Files selected for processing (3)
  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
  • tests/setup_nu_test.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Trackdubllc/Trackdub (manual)
  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Greptile Review
  • GitHub Check: Real-Nu acceptance (windows-latest)
  • GitHub Check: Test (windows-latest)
  • GitHub Check: Analyze (rust)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Use anyhow::Result with .context("what failed") for application code, thiserror for library types callers match on, and avoid panics in library code by returning Result.

**/*.rs: Use Rust 2021 edition conventions and match existing naming, module layout, and documentation level in edited files.
Use anyhow::Result with .context(...) in application code; use thiserror for library error types that callers match on.
Use clap derive macros for CLI definitions.
Use serde with serde_json or toml for serialization.
Function parameters must use &Path, not &PathBuf.
Error paths must return anyhow::Result with context, and library code must not panic.
Unit tests must use injectable seams such as FakeCandidateRunner and registrars; do not spawn real nu in unit tests.
Real-Nu acceptance tests should be marked #[ignore] and run separately when activation or nupm-import behavior changes.
Every new mutating code path must acquire the mutation lock and snapshot the lockfile before writes.
Mutating commands, including install, remove, update, gc, and nupm import, must call acquire_mutation_lock(root).
Lockfiles, journals, and state files must be written atomically using write_json_atomic.
numan install must write only to $NUMAN_ROOT and must not invoke Nu or register plugins/autoloads.
Only activate and deactivate may modify Nu integration state.
Treat the lockfile as the authoritative source of truth; derived projections such as autoload state are not authoritative.
Install payloads must use versioned, content-addressed paths and must never be overwritten in place.
Never overwrite foreign autoload files; respect OWNERSHIP_MARKER.
Pass plugin paths through environment variables only; do not use runtime interpolation in Nu program strings.
The nupm boundary must remain read-only toward NUPM_HOME, must not execute build.nu, and must not perform bidirectional synchronization.

Use Rust 2021 conventions; the crate's MSRV is...

Files:

  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
  • tests/setup_nu_test.rs
src/{cmd,state,install}/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Call create_snapshot() before mutations performed by install, update, remove, activate, deactivate, or nupm-import; garbage collection must treat payloads referenced by every snapshot as live roots.

Files:

  • src/cmd/setup.rs
src/cmd/**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

Keep clap subcommand handlers thin; delegate domain logic to core/ or installation logic to install/.

Files:

  • src/cmd/setup.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,toml}: All changes must pass formatting and linting: cargo fmt and cargo clippy -- -D warnings.
Behavior changes require corresponding tests, including relevant failure paths.

Files:

  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
  • tests/setup_nu_test.rs
**/*.{rs,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update documentation when changing structure, conventions, or user-visible behavior, using AGENTS.md, docs/, or command help as appropriate.

Files:

  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
  • tests/setup_nu_test.rs
**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Redact secrets when reporting relevant logs or lockfile excerpts in issues.

Files:

  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
  • tests/setup_nu_test.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.rs: Use anyhow::Result for application code and thiserror for library errors; add error context with .context(...) or ?, and never panic in library code.
Use &Path rather than &PathBuf in function parameters.

Files:

  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.rs: Keep unit tests inline with source modules and integration tests under tests/; test platform-specific code with mock platforms.
Real-Nu acceptance tests may be ignored and must be run with cargo test -- --ignored; unit tests should use injected fakes rather than a real Nu process.

Files:

  • tests/setup_nu_test.rs
🔍 Remote MCP DeepWiki, GitHub Copilot

Relevant review context

  • PR #70’s actual diff includes an unrelated scripts/apply_install_from_archive_fix.py file, despite the PR description claiming only four setup-related files. This script edits src/nu/bootstrap.rs programmatically and should be reviewed for intentional inclusion.

  • The shared helper’s documented contract is:

    • --yes: proceed and emit an audit line.
    • TTY without --yes: allow the caller’s subsequent prompt.
    • Non-TTY without --yes: emit an audit refusal and fail.
      The new bootstrap call uses the injectable require_tty_or_yes_with_tty, matching this contract.
  • PR #70 is explicitly gated on PR #69, which supplies the other destructive setup call sites and targets the same require_tty_or_yes audit behavior. Both PR #69 and #70 are currently open and blocked.

  • PR #71 independently describes the broader setup architecture: destructive setup operations should require TTY/--yes, while version management uses active-version markers and journaled migration. This confirms that the reviewed changes sit within a larger, still-unmerged setup refactor.

  • PR #70’s current checks show successful formatting, Clippy, package, Linux/macOS tests, and real-Nu acceptance on Linux/macOS. Windows tests, Windows real-Nu acceptance, Rust analysis, and Greptile review were still in progress; CodeQL completed with a neutral conclusion.

  • DeepWiki could not locate the referenced files or helper in its indexed repository state, so it provides no reliable architectural validation for this PR.

🔇 Additional comments (3)
src/nu/bootstrap.rs (1)

5-5: LGTM!

Also applies to: 210-210, 312-312, 461-477, 680-684, 716-731, 748-756, 769-773, 1027-1027, 1058-1082

tests/setup_nu_test.rs (1)

12-12: LGTM!

Also applies to: 41-41, 55-76, 283-311

src/cmd/setup.rs (1)

1-1: LGTM!

Also applies to: 221-249, 293-293, 342-348, 369-371, 406-412, 431-434, 448-451, 800-820, 888-912, 991-992

Comment thread src/nu/bootstrap.rs Outdated
greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 3, 2026
Keep the (audit) string contract; share the formatter from util::confirm
so other destructive hoist surfaces need not depend on Nu bootstrap.

Co-authored-by: Cursor <cursoragent@cursor.com>
When consent is not hoisted, refuse non-TTY PATH/active-version updates
without --yes using options.is_tty, matching other destructive setup paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/nu/bootstrap.rs (1)

486-490: ⚠️ Potential issue | 🟠 Major

Keep direct registration behind the shared consent gate.

When caller_consented_destructive is false, register_existing_nu still reaches confirm_or_bail without require_tty_or_yes_with_tty. Because confirm_or_bail auto-confirms non-TTY input, direct registration and setup nu use or doctor-repair paths can mutate PATH without a TTY or --yes.

Unless PR #69 adds an outer gate for every caller, call the shared gate before confirm_or_bail and use options.is_tty when it is set. This is the same unresolved finding from the previous review.

#!/bin/bash
set -euo pipefail
rg -n -C 8 \
  'register_existing_nu|caller_consented_destructive|require_tty_or_yes(_with_tty)?' \
  src tests
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/nu/bootstrap.rs` around lines 486 - 490, Ensure register_existing_nu
routes every non-consented destructive registration through
require_tty_or_yes_with_tty before confirm_or_bail, including direct CLI and
doctor-repair callers. When options.is_tty is set, pass that value to the shared
gate; preserve the existing caller_consented_destructive bypass for callers
already gated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/setup_nu_test.rs`:
- Around line 275-283: Align register_existing_nu_audit_text_is_stable and its
documentation with the actual hoisted_audit_message formatter contract, since
the test does not exercise register_existing_nu. Alternatively, add a focused
test that invokes register_existing_nu and verifies its emitted audit output,
while retaining a separate formatter test if needed.

---

Outside diff comments:
In `@src/nu/bootstrap.rs`:
- Around line 486-490: Ensure register_existing_nu routes every non-consented
destructive registration through require_tty_or_yes_with_tty before
confirm_or_bail, including direct CLI and doctor-repair callers. When
options.is_tty is set, pass that value to the shared gate; preserve the existing
caller_consented_destructive bypass for callers already gated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e78ef47e-d214-4c4a-ae2e-6d3429a2bc53

📥 Commits

Reviewing files that changed from the base of the PR and between b2d156c and 7b702b1.

📒 Files selected for processing (4)
  • src/cmd/setup.rs
  • src/nu/bootstrap.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • Trackdubllc/Trackdub (manual)
  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (4)
  • GitHub Check: Greptile Review
  • GitHub Check: Test (windows-latest)
  • GitHub Check: Real-Nu acceptance (windows-latest)
  • GitHub Check: Analyze (rust)
🧰 Additional context used
📓 Path-based instructions (10)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

**/*: Use Serena's semantic, symbol-aware tools as the primary tools for reading and editing code; use built-in Read, Glob, Grep, and Edit only under the stated exceptions.
Before editing a code file, inspect its symbol overview, read the specific symbols being changed, and edit them with Serena's symbol-aware tools.
Understand the existing code before changing it and make the smallest change that satisfies the request; avoid unrelated cleanup, premature abstractions, unnecessary error handling, feature flags, and compatibility shims.
Prefer editing existing files over creating new ones, and never create Markdown or README files unless explicitly requested.
For exploratory questions, provide a 2–3 sentence recommendation with the main tradeoff and do not implement until the user agrees.
For UI or frontend changes that cannot be tested in a browser, explicitly state that browser testing was not performed rather than claiming success.
Address security issues when discovered, including injection, XSS, SQL injection, path traversal, and secret leaks.
Pause and obtain confirmation before destructive, hard-to-reverse, externally visible, or third-party-upload actions, including deleting files or branches, dropping tables, force-pushing, modifying CI/CD, posting externally, or uploading content.
When blocked, investigate the root cause instead of bypassing it with --no-verify, --force, or deletion; investigate unfamiliar files, branches, and configuration before deleting them.
Only commit when explicitly asked; do not proactively update git configuration or push changes.
Do not skip Git hooks unless explicitly asked; if a pre-commit hook fails, fix the issue, re-stage, and create a new commit rather than amending.
Stage files by name rather than using git add -A or git add ., to avoid accidentally including secrets or large binaries.
Use a HEREDOC for commit messages, and add co-author attribution only when the user explicitly requests the exact trailer.
Do not force-pus...

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.{js,jsx,ts,tsx,py,java,go,rs,rb,php,c,cpp,h,hpp,cs,swift,kt,kts}

📄 CodeRabbit inference engine (CLAUDE.md)

Add comments only when the WHY is non-obvious; do not narrate what the code does, reference the current task, or reference the PR in comments.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
!**/.env,!**/credentials.json,!**/*.pem

📄 CodeRabbit inference engine (CLAUDE.md)

Do not commit files that appear to contain secrets, including .env, credentials.json, and PEM files; warn before doing so even if explicitly requested.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Use anyhow::Result for application code, thiserror for library error types, add context with .context(...) or ?, and never panic in library code; return errors instead.
Use &Path rather than &PathBuf in function parameters.
Add unit tests inline with source modules and integration tests under tests/; test-first development is expected, and platform-specific code must be tested with mock platforms.

**/*.rs: Use the Rust 2021 edition.
Use anyhow::Result with .context(...) in application code; use thiserror for library error types that callers match on.
Use clap derive macros for CLI definitions.
Use serde with serde_json or toml for serialization.
Function parameters must use &Path, not &PathBuf.
Library code must not panic; error paths should return anyhow::Result with context where appropriate.
Add or update tests for behavior changes, including relevant failure paths.
New mutating code paths must acquire the mutation lock via acquire_mutation_lock(root) and snapshot the lockfile before writes.
Lockfile, journal, and state-file JSON writes must use write_json_atomic.
numan install must write only to $NUMAN_ROOT; it must not invoke Nu or register plugins/autoloads.
Only activate and deactivate may modify Nu integration state.
Treat the lockfile as the authoritative source of truth; derived projections such as autoload state must not be authoritative.
Install payloads under versioned, content-addressed paths and never overwrite them in place.
Never overwrite foreign autoload files; respect OWNERSHIP_MARKER.
Pass plugin paths through environment variables only; do not use runtime interpolation in Nu program strings.

**/*.rs: All CI gates must pass: cargo test, cargo clippy -- -D warnings, and cargo fmt --check.
Every mutating command—including install, remove, update, gc, and future nupm import—must call acquire_mutation_lock(root).
Lockfiles, journals, and state files must use `write_js...

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Use dependency conventions: serde/serde_json for JSON, toml for configuration, clap derive macros for CLI parsing, and anyhow/thiserror according to application versus library boundaries.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • src/nu/bootstrap.rs
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run and keep cargo fmt/rustfmt clean, and ensure cargo clippy -- -D warnings passes.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.{rs,nu}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,nu}: Real-Nu acceptance tests must be marked #[ignore] and should be run when changes affect activation or nupm import; unit tests must not spawn real nu and should use injectable seams such as FakeCandidateRunner or registrars.
The nupm integration must be read-only toward NUPM_HOME, must not execute build.nu, and must not perform bidirectional synchronization.

Unit tests must use FakeCandidateRunner or injectable registrars and must not spawn a real nu process.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.{rs,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Match existing naming, module layout, and documentation level in the file being edited; update AGENTS.md, docs/, or command help when structure, conventions, or user-visible behavior changes.

Tests must cover failure modes, not only successful execution.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
**/*.{rs,md,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use the repository's established serialization and module conventions rather than introducing unrelated refactors.

Files:

  • src/cmd/setup.rs
  • src/util/confirm.rs
  • tests/setup_nu_test.rs
  • src/nu/bootstrap.rs
tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Use injected fakes and runners for activation-related unit tests; do not spawn a real Nu binary in unit tests.

Files:

  • tests/setup_nu_test.rs
🔍 Remote MCP DeepWiki, GitHub Copilot

Relevant review context

  • The PR’s diff includes an unrelated scripts/apply_install_from_archive_fix.py script that modifies src/nu/bootstrap.rs to use versioned installation paths. It is not listed in the PR description and uses bare assert checks, making its inclusion worth clarifying.

  • An earlier review identified that direct register_existing_nu callers could still bypass the TTY gate; that comment is now outdated, but the current diff still only adds the gate to bootstrap setup and managed removal. Verify whether direct registration is intentionally covered by the prerequisite PR #69 or requires an explicit guard here.

  • The golden audit test now constructs expected output with parent.display(), addressing the prior cross-platform path concern. However, it still reconstructs the format string instead of comparing against a literal, so it verifies consistency with the helper implementation more than protection against accidental wording changes.

  • PR #70 is blocked and explicitly depends on PR #69. PR #69 introduces the remaining destructive setup call sites and the broader journaled migration flow.

  • Current checks: formatting, Clippy, package, MSRV, Ubuntu tests, Ubuntu/macOS real-Nu acceptance, and action/Python analysis passed. Windows tests, Windows real-Nu acceptance, macOS tests, Rust analysis, and Greptile review were still in progress; CodeQL completed with a neutral conclusion.

  • DeepWiki could not locate the relevant numan files, so it provided no reliable architectural validation.

🔇 Additional comments (4)
src/util/confirm.rs (1)

90-106: LGTM!

Also applies to: 148-158

src/nu/bootstrap.rs (1)

24-35: LGTM!

Also applies to: 457-459, 680-684, 735-739, 769-786, 1028-1028, 1058-1083

tests/setup_nu_test.rs (1)

70-70: LGTM!

Also applies to: 284-310

src/cmd/setup.rs (1)

11-22: LGTM!

Also applies to: 257-257, 367-378, 430-441, 458-472, 854-874

Comment thread tests/setup_nu_test.rs
@tonythethompson
tonythethompson enabled auto-merge (squash) August 3, 2026 03:23
@tonythethompson
tonythethompson merged commit c7b44d6 into master Aug 3, 2026
26 checks passed
@tonythethompson
tonythethompson deleted the feature/require-tty-or-yes-bootstrap branch August 3, 2026 03:27
@linear-code

linear-code Bot commented Aug 3, 2026

Copy link
Copy Markdown

TS-117

cursor Bot pushed a commit that referenced this pull request Aug 3, 2026
Take #70 injectable is_tty / require_tty_or_yes_with_tty for download and
already-installed setup paths. Keep PR 69 refuse-in-place --force behavior
and both sides' non-TTY regression tests.

Co-authored-by: Anthony Thompson <github@trackdub.com>
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.

3 participants