Skip to content

feat(wizard): ask before changing global agent settings - #614

Merged
theCodeDrift merged 2 commits into
mainfrom
global-trust-opt-in
Nov 5, 2026
Merged

theCodeDrift merged 2 commits into
mainfrom
global-trust-opt-in

Conversation

@theCodeDrift

Copy link
Copy Markdown
Member

The wizard asked one question for every settings edit, so saying no to the entry in ~/.claude/settings.json cancelled the whole install. Nobody could install Taskless and skip the edit outside their project. This gives that edit its own question.

postmanlabs/postman-app-support#14370 is the motivation: an installer changing global agent config without a real opt-in. We already asked, but a question bundled with the install isn't much of a choice, and skipping costs little, because the launcher and pin keep working and the agent asks for approval more often.

What changes

  • The entry is asked about after the summary and before anything is written.
  • The question defaults to no, so Enter leaves the user's settings alone.
  • The step explains the launcher and pin, why auto mode can't see them, that the entry applies to every project on the machine, the exact text, how to undo it, and what skipping costs.
  • Declining finishes the install and prints one line, not the red SKIPPED (global): block. Cancelling the prompt still writes nothing.

Unchanged: init --no-interactive and --json still never write outside the project. The entry's text is the same, so no existing entry goes stale.

Worth a look

  • This reverses the "one grouped settings question" decision in agent-global-trust (287238c3).
  • A user-level entry follows the launcher's path, so it also covers ./.taskless/bin/cli.mjs in any repository someone clones. A manual probe on 2026-10-19 (one run) passed a launcher swapped to run another package. The prompt now says this; narrowing the entry would mark every existing entry stale, so it is left out of this PR.

Verified with pnpm typecheck, pnpm lint and the CLI suite, using mocked prompts. Not yet run in a real terminal.

The global trust entry shared one question with the install, so declining it
cancelled the install. It now has its own step, which explains why the entry is
needed and how far it reaches, and defaults to no. Declining still installs.
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @theCodeDrift's task in 3m 32s —— View job


Review mode: incremental — read 0 prior review thread(s) before reviewing.

.prior-review.json contains no reviews, review threads, or top-level comments beyond the @claude /review trigger itself, so this is the first review of this PR. Everything below is [New].

  • Read prior review data (none found)
  • Read PR diff and changed files
  • Review wizard step, global-trust logic, tests, spec docs
  • Post findings

Summary

This PR gives the global ~/.claude/settings.json edit its own opt-in question, defaulting to no, asked after the summary confirmation and before any write. I read the full diff plus the complete contents of packages/cli/src/wizard/index.ts, packages/cli/src/install/global-trust.ts, packages/cli/src/wizard/steps/summary.ts, packages/cli/src/wizard/steps/global-trust.ts, and packages/cli/src/wizard/ask.ts to check the control flow end-to-end (not just the diff hunks).

[New] Control flow traced and looks correct:

  • offered/trusted/declined in wizard/index.ts correctly gate the write, the SKIPPED (global): suppression, and the new one-line decline notice. The &&/await short-circuit (offered && (await promptGlobalTrust(...))) correctly skips calling promptGlobalTrust when nothing is offered.
  • The re-read-after-write pattern (globalTrust.filter((o) => !needsWrite(o)) when declined) correctly keeps warnings for genuinely unparseable (skipped) files while suppressing them for the entry the user just declined — matches the new "A decline is not warned about" / "A skipped file warns after a wizard install" scenarios.
  • ask("global-trust", ...) is called before any file is written (prior to ensureTasklessDirectory/applyInstallPlan/syncPermissions(write:true)), so cancelling the new prompt leaves everything unwritten, matching the new test and spec scenario.
  • renderSummaryAndConfirm's editsSettings no longer factors in the global outcome, so when only the global entry needs attention and all project edits are already in place, the summary step asks nothing and only the new global-trust question is shown — matches the updated cli-init/agent-global-trust specs and the corresponding test change.
  • No stray callers of the old 3-arg renderSummaryAndConfirm or the old describeGlobalTrust return shape ({replace, what, where}) remain; all call sites and tests were updated consistently with the new GlobalTrustOffer shape (file, before, after).

[New] Minor, non-blocking observation: in wizard/steps/global-trust.ts, each offer's ALLOW (global):/REPLACE (global): line is laid out via its own single-element layoutSettings([...]) call, so label padding is computed per-offer rather than across all offers (unlike the project-edits block in summary.ts, which pads to the widest label across all entries). With only one harness (claudeCode) in GLOBAL_TRUST today this never produces a visible misalignment, but if a second harness is ever added with a differently-sized label, simultaneous ALLOW/REPLACE lines in the same message would not align. Worth a glance if/when the harness list grows, not worth blocking on now.

No correctness, security, or test-adequacy issues found. Test coverage for the new decline/cancel/accept/stale/already-present paths in wizard-integration.test.ts is thorough.

Note: I wasn't able to resolve this session's actual CI job run URL (environment lookups were blocked), so I'm omitting the job-run link rather than guessing one.

@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @github-actions — "Claude finished @theCodeDrift's task in 3m 32s"
#614 (comment)

Declined the per-offer label padding note. Only one harness exists today, so no two labels can misalign; it's worth revisiting if a second harness joins the list.

— AI Coding Agent

@theCodeDrift
theCodeDrift merged commit 9a73849 into main Nov 5, 2026
8 checks passed
@theCodeDrift
theCodeDrift deleted the global-trust-opt-in branch November 5, 2026 21:17
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.

1 participant