#!/usr/bin/env node /** * patch-x07-seq-step-calc.js * 修复 agent-isolation-gate.js B2 规则: seq 三参数形式步长被忽略 * seq FIRST STEP LAST → n = floor((LAST - FIRST) / STEP) + 1 * * 幂等: SENTINEL 标记 */ 'use strict'; const fs = require('fs'); const path = require('path'); const SENTINEL = '[PATCH-X07-SEQ-STEP]'; const TARGET = path.join(__dirname, '..', '..', 'hooks', 'agent-isolation-gate.js'); if (!fs.existsSync(TARGET)) { console.log('SKIP: target not found'); process.exit(0); } let src = fs.readFileSync(TARGET, 'utf8'); if (src.includes(SENTINEL)) { console.log('SKIP: already patched'); process.exit(0); } // 替换 B2 seq 计算块 (行 80-86) const oldBlock = [ " const seqMatch = c.match(/\\bseq\\s+(\\d+)(?:\\s+(\\d+))?(?:\\s+(\\d+))?/);", " if (seqMatch) {", " const a = parseInt(seqMatch[1], 10);", " const b = seqMatch[2] ? parseInt(seqMatch[2], 10) : null;", " const z = seqMatch[3] ? parseInt(seqMatch[3], 10) : (b !== null ? b : a);", " const n = b !== null && z !== null ? Math.max(0, z - a + 1) : a;", " if (n >= 6) return { rule: 'B2', detail: 'seq ' + n };", " }" ].join('\n'); // seq 语义: seq LAST / seq FIRST LAST / seq FIRST STEP LAST const newBlock = [ " const seqMatch = c.match(/\\bseq\\s+(\\d+)(?:\\s+(\\d+))?(?:\\s+(\\d+))?/); // " + SENTINEL, " if (seqMatch) {", " let n;", " const g1 = parseInt(seqMatch[1], 10);", " const g2 = seqMatch[2] ? parseInt(seqMatch[2], 10) : null;", " const g3 = seqMatch[3] ? parseInt(seqMatch[3], 10) : null;", " if (g3 !== null) {", " // seq FIRST STEP LAST", " const step = Math.max(1, g2);", " n = Math.max(0, Math.floor((g3 - g1) / step) + 1);", " } else if (g2 !== null) {", " // seq FIRST LAST", " n = Math.max(0, g2 - g1 + 1);", " } else {", " // seq LAST (从 1 到 LAST)", " n = g1;", " }", " if (n >= 6) return { rule: 'B2', detail: 'seq ' + n };", " }" ].join('\n'); if (!src.includes(oldBlock)) { console.error('FAIL: old block not found (already modified?)'); process.exit(1); } src = src.replace(oldBlock, newBlock); const tmp = TARGET + '.tmp.' + process.pid; fs.writeFileSync(tmp, src, 'utf8'); fs.renameSync(tmp, TARGET); // 冒烟验证 const patched = fs.readFileSync(TARGET, 'utf8'); if (!patched.includes(SENTINEL)) { console.error('FAIL: sentinel missing after patch'); process.exit(1); } if (!patched.includes('Math.floor((g3 - g1) / step)')) { console.error('FAIL: step formula missing'); process.exit(1); } console.log('OK: X07 seq step calc patched');