// Final simulation: exact v0.5.96 flow with realistic DOM const {generateApprovalObserverScript} = require('../out/observer-script'); let s = generateApprovalObserverScript(18080); try { new Function(s); console.log('SYNTAX: OK'); } catch(e) { console.log('SYNTAX ERROR:', e.message); process.exit(1); } let promptRe = /[\u003e\u00bb\u276f]\s+(.+)/; let stripRe = /\s*(content_copy|content_paste|play_arrow|check_circle|keyboard_arrow[_a-z]*)\s*$/; let iconFilterRe = /^(content_copy|content_paste|play_arrow|check_circle|chevron_|keyboard_arrow|more_horiz|more_vert|expand_|alternate_email|arrow_drop)/; // Realistic scenario: "Running command" div has siblings including a copy button // The actual DOM probably has a structure like: // div "Running command" // span/div with the copy icon (textContent = "> content_copy" or just "content_copy") // div with the actual prompt+command // div with the buttons function v31_simulate(name, siblings) { console.log('\n=== ' + name + ' ==='); // Step 1: Find "Running command" header let rcIdx = -1; for (let i = 0; i < siblings.length; i++) { let t = siblings[i].trim(); if (t === 'Running command' || (t.indexOf('Running command') !== -1 && t.length < 30)) { rcIdx = i; break; } } if (rcIdx < 0) { console.log(' NO RC HEADER'); return; } // Step 2: Collect candidates (filter icons and buttons) let cands = []; for (let i = 0; i < siblings.length; i++) { if (i === rcIdx) continue; let t = siblings[i].trim(); if (t.length < 5) continue; if (iconFilterRe.test(t)) { console.log(' FILTER icon: "' + t.substring(0,40) + '"'); continue; } if (/^(Always|Run|Allow|Cancel|Deny|keyboard_arrow)/i.test(t)) { console.log(' FILTER btn: "' + t.substring(0,40) + '"'); continue; } if (t.indexOf('Always run') !== -1 && t.indexOf('Cancel') !== -1) { console.log(' FILTER btn-bar: "' + t.substring(0,40) + '"'); continue; } cands.push(t); console.log(' CANDIDATE: "' + t.substring(0,60) + '" (len=' + t.length + ')'); } // Step 3: Sort by length (longest first) cands.sort((a,b) => b.length - a.length); // Step 4: Extract command from best candidate for (let cand of cands) { let m = promptRe.exec(cand); if (m && m[1].trim().length > 3) { let cmdV = m[1].trim().replace(stripRe, '').trim(); if (cmdV.length < 3) { console.log(' SKIP (too short after strip): "' + cmdV + '"'); continue; } if (/^(Always|Run|Allow|Cancel|Deny)/i.test(cmdV)) continue; console.log(' EXTRACTED: "' + cmdV + '"'); return; } if (cand.length > 10 && /[\u276f\u003e]/.test(cand)) { let raw = cand.replace(stripRe, '').trim(); console.log(' EXTRACTED (raw): "' + raw + '"'); return; } } console.log(' NO MATCH - will fallback to "Always run"'); } // Scenario A: What ACTUALLY happened (3 siblings, "content_copy" mixed in command text) v31_simulate('A: Icon in command text', [ 'Running command', '\u276f gravity_control > Start-Sleep 12; $logFile content_copy', 'Always run keyboard_arrow_up Cancel' ]); // Scenario B: Copy button as separate small div v31_simulate('B: Icon as separate div + command div', [ 'Running command', '> content_copy', '\u276f gravity_control > npm run compile', 'Always run Cancel' ]); // Scenario C: Just "content_copy" standalone (no >) v31_simulate('C: Standalone icon + command', [ 'Running command', 'content_copy', '\u276f gravity_control > git push origin main', 'Always run Cancel' ]); // Scenario D: Multiple icons mixed v31_simulate('D: Multiple icons + command', [ 'Running command', 'play_arrow', '> content_copy', '\u276f gravity_control > node -e "console.log(1)" content_copy', 'Always run keyboard_arrow_up Cancel' ]); // Scenario E: Edge - no command, only prompt v31_simulate('E: Prompt only', [ 'Running command', '\u276f gravity_control > ', 'Always run Cancel' ]); // Scenario F: The v0.5.95 cmdV=content_copy case // This implies regex matched "content_copy" from a "> content_copy" sibling // and there was no longer sibling v31_simulate('F: Only icon sibling (worst case)', [ 'Running command', '> content_copy', 'Always run Cancel' ]); console.log('\n=== SIMULATION COMPLETE ===');