fix(observer): v32 터미널 프롬프트 조기감지 — JUNK/PROMPT 필터 전에 명령어 추출 (v0.5.97)
근본원인: code 요소의 textContent '❯ project > command'가 PowerShell 키워드 (return, function, const)를 포함할 수 있어 JUNK_CODE_RE에 잘못 걸림. v32: ❯ 마커로 시작하는 code 텍스트는 JUNK/PROMPT 전에 명령어 직접 추출. 14/14 E2E 테스트 통과.
This commit is contained in:
114
extension/scratch/verify_final.js
Normal file
114
extension/scratch/verify_final.js
Normal file
@@ -0,0 +1,114 @@
|
||||
// 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 ===');
|
||||
Reference in New Issue
Block a user