Summary
runBulkScanWizard() accepts an AbortSignal and propagates it through GitHub authentication/discovery requests, but then stops forwarding it to several blocking interactive prompts.
Once discovery reaches account/repository selection, output-directory entry, or the final confirmation, cancellation can no longer interrupt the prompt even though BulkScanPrompt already exposes a signal parameter for every prompt method.
Reproduction / evidence
The prompt contract is signal-aware:
confirm(question, defaultValue?, signal?): Promise<boolean>;
input(question, defaultValue?, signal?): Promise<string>;
select(question, options, presentation?, signal?): Promise<Value>;
Current main at 37bf87a692fc72d41f7312cc48808d699d204fba correctly forwards the signal to createGitHub() and discoverGitHubRepositories(), but omits it at these call sites:
selectGitHubOwner(...)
-> prompt.select(...); // no signal
selectGitHubRepositories(...)
-> prompt.select(...); // no signal
prompt.input(
"Where should scan results be saved?",
"./security-scans",
); // no signal
prompt.confirm("Start scanning?"); // no signal
Minimal deterministic reproduction with an injected BulkScanPrompt:
- let GitHub discovery return one active repository;
- pass an
AbortSignal to runBulkScanWizard();
- instrument
select, input, and confirm to record the signal they receive;
- current
main records undefined at those interactive boundaries despite the wizard having the caller's signal.
With a real terminal prompt, cancellation during one of those waits cannot reach Inquirer until the user supplies input or the process is otherwise terminated.
Expected behavior
Every blocking prompt in a signal-aware wizard should receive the same caller AbortSignal that is already used for GitHub requests, so cancellation remains effective throughout the workflow.
Root cause
The signal is threaded through the network/discovery helpers but was omitted from the prompt call sites. selectGitHubRepositories() does not currently accept a signal at all, and selectGitHubOwner() accepts one but does not pass it to prompt.select().
Suggested fix
- pass
signal to account selection;
- add
signal to selectGitHubRepositories() and pass it to repository selection;
- pass
signal to output-directory input and final confirmation;
- add focused prompt-boundary regression coverage proving all blocking prompts receive the caller signal.
Impact
This is a cancellation/reliability bug rather than data corruption. A user or automation can request cancellation successfully during GitHub discovery, then have the same cancellation become ineffective once the wizard is waiting for terminal input.
Summary
runBulkScanWizard()accepts anAbortSignaland propagates it through GitHub authentication/discovery requests, but then stops forwarding it to several blocking interactive prompts.Once discovery reaches account/repository selection, output-directory entry, or the final confirmation, cancellation can no longer interrupt the prompt even though
BulkScanPromptalready exposes a signal parameter for every prompt method.Reproduction / evidence
The prompt contract is signal-aware:
Current
mainat37bf87a692fc72d41f7312cc48808d699d204fbacorrectly forwards the signal tocreateGitHub()anddiscoverGitHubRepositories(), but omits it at these call sites:Minimal deterministic reproduction with an injected
BulkScanPrompt:AbortSignaltorunBulkScanWizard();select,input, andconfirmto record the signal they receive;mainrecordsundefinedat those interactive boundaries despite the wizard having the caller's signal.With a real terminal prompt, cancellation during one of those waits cannot reach Inquirer until the user supplies input or the process is otherwise terminated.
Expected behavior
Every blocking prompt in a signal-aware wizard should receive the same caller
AbortSignalthat is already used for GitHub requests, so cancellation remains effective throughout the workflow.Root cause
The signal is threaded through the network/discovery helpers but was omitted from the prompt call sites.
selectGitHubRepositories()does not currently accept a signal at all, andselectGitHubOwner()accepts one but does not pass it toprompt.select().Suggested fix
signalto account selection;signaltoselectGitHubRepositories()and pass it to repository selection;signalto output-directory input and final confirmation;Impact
This is a cancellation/reliability bug rather than data corruption. A user or automation can request cancellation successfully during GitHub discovery, then have the same cancellation become ineffective once the wizard is waiting for terminal input.