/** * TodoWrite vs Skill transcript verifier — router-gate v4 spec §3.9 + v4.1 (Direction 4). * Pure: ловит TodoWrite claims "invoked X skill" без actual Skill tool call + erasure. * v4.1: hard sync — completed item claiming skill but not invoked → block next mutating. */ export const SKILL_MENTION_PATTERNS = [ /superpowers:[a-z-]+/g, /Skill\(([^)]+)\)/g, /\binvoke\s+([a-z][a-z0-9-]*)/gi, /(? skillNameMatches(mention.skill_name, c.skill_name)); if (!matched) mismatches.push(mention); } return { mismatches }; } export function detectErasure(historySnapshots) { const erased = []; for (const snap of historySnapshots || []) { const removed = snap.diff?.removed || []; for (const item of removed) { const mentions = extractSkillMentions([item]); if (mentions.length > 0) erased.push({ snapshot_ts: snap.ts, item, mentions }); } } return { erased }; } export function hardSyncCheck(skillMentions, actualSkillCalls) { for (const mention of skillMentions) { if (mention.status !== 'completed') continue; const wasInvoked = (actualSkillCalls || []).some((c) => skillNameMatches(mention.skill_name, c.skill_name)); if (!wasInvoked) { return { action: 'hard_block_next_mutating', reason: `v4.1 TodoWrite hard sync: item "${mention.text}" marked completed claims Skill(${mention.skill_name}) invoked, но Skill tool call отсутствует. Либо invoke Skill сейчас, либо edit TodoWrite чтобы remove false claim.`, }; } } return { action: 'allow' }; }