From ed1fe99c3b81d20e8063cb30fcc8c1fbac581365 Mon Sep 17 00:00:00 2001 From: nrslib Date: Sun, 1 Feb 2026 03:15:45 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20detectRuleIndex=20=E3=82=92=E6=9C=80?= =?UTF-8?q?=E5=BE=8C=E3=81=AE=E3=83=9E=E3=83=83=E3=83=81=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=81=99=E3=82=8B=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__tests__/client.test.ts | 9 +++++++++ src/claude/client.ts | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/__tests__/client.test.ts b/src/__tests__/client.test.ts index 55611e1..108c669 100644 --- a/src/__tests__/client.test.ts +++ b/src/__tests__/client.test.ts @@ -66,4 +66,13 @@ describe('detectRuleIndex', () => { expect(detectRuleIndex('[AI_REVIEW:1]', 'ai_review')).toBe(0); expect(detectRuleIndex('[SECURITY_FIX:2]', 'security_fix')).toBe(1); }); + + it('should detect last occurrence when multiple tags exist', () => { + const content = 'Previous: [AI_REVIEW:1]\n\nActual result:\n[AI_REVIEW:2]'; + expect(detectRuleIndex(content, 'ai_review')).toBe(1); + }); + + it('should detect last match with multiple occurrences', () => { + expect(detectRuleIndex('[PLAN:1] then [PLAN:2] finally [PLAN:3]', 'plan')).toBe(2); + }); }); diff --git a/src/claude/client.ts b/src/claude/client.ts index f37a19c..66e5de0 100644 --- a/src/claude/client.ts +++ b/src/claude/client.ts @@ -43,8 +43,9 @@ export interface ClaudeCallOptions { */ export function detectRuleIndex(content: string, stepName: string): number { const tag = stepName.toUpperCase(); - const regex = new RegExp(`\\[${tag}:(\\d+)\\]`, 'i'); - const match = content.match(regex); + const regex = new RegExp(`\\[${tag}:(\\d+)\\]`, 'gi'); + const matches = [...content.matchAll(regex)]; + const match = matches.at(-1); if (match?.[1]) { const index = Number.parseInt(match[1], 10) - 1; return index >= 0 ? index : -1;