3export const destructiveGitPatterns = [ 4 /^stash(?!\s+(list|show))\b/, /reset\b.*--hard/, 5 /checkout (HEAD --|-- )/, /^restore /, /revert /, /clean -f/, 6 /push\b.*(--force|-f)/, /branch -D/, 10const confirmFlagRe = /^--confirmedByUser(?:=(.*))?$/ 12export const hasUserConfirmedGit = (args: string[]) => { 13 for (let i = 0; i < args.length; i++) { 14 const m = args[i].match(confirmFlagRe) 16 const val = m[1] ?? args[i + 1] 17 if (val === ptConfirmSecret) return true 22export const stripConfirmFlag = (args: string[]) => { 23 const out: string[] = [] 24 for (let i = 0; i < args.length; i++) { 25 const m = args[i].match(confirmFlagRe) 26 if (!m) { out.push(args[i]); continue } 27 if (m[1] === undefined && args[i + 1] === ptConfirmSecret) i++ 32export const isDestructiveGitArgs = (args: string[]) => { 33 const argStr = args.join(' ') 34 return destructiveGitPatterns.some(p => p.test(argStr)) 37const gitTokenRe = /(^|\s)(?:[^\s;|&<>]*\/)?git(\s|$)/ 38const shellSepRe = /[;|&<>]/ 40export const findUnconfirmedDestructiveGit = (cmd: string): string | null => { 41 for (const segment of cmd.split(shellSepRe)) { 42 const m = segment.match(gitTokenRe) 44 const gitIdx = segment.indexOf('git', m.index!) 45 const argStr = segment.slice(gitIdx + 3).trim() 47 const args = argStr.split(/\s+/) 48 if (hasUserConfirmedGit(args)) continue 49 if (isDestructiveGitArgs(args)) return `git ${argStr}`