diff --git a/packages/workflows/src/executor-shared.test.ts b/packages/workflows/src/executor-shared.test.ts index 84346f13..80915621 100644 --- a/packages/workflows/src/executor-shared.test.ts +++ b/packages/workflows/src/executor-shared.test.ts @@ -167,6 +167,50 @@ describe('substituteWorkflowVariables', () => { expect(prompt).toBe('Issue: context-data. External: context-data'); }); + it('does not treat context variables as prefixes of longer identifiers', () => { + const { prompt, contextSubstituted } = substituteWorkflowVariables( + 'Context: $CONTEXT. File: $CONTEXT_FILE. External path: $EXTERNAL_CONTEXT_PATH. IssueId: $ISSUE_CONTEXT_ID', + 'run-1', + 'msg', + '/tmp', + 'main', + 'docs/', + 'context-data' + ); + expect(prompt).toBe( + 'Context: context-data. File: $CONTEXT_FILE. External path: $EXTERNAL_CONTEXT_PATH. IssueId: $ISSUE_CONTEXT_ID' + ); + expect(contextSubstituted).toBe(true); + }); + + it('does not substitute $ISSUE_CONTEXT when followed by identifier characters', () => { + const { prompt } = substituteWorkflowVariables( + 'Issue: $ISSUE_CONTEXT. ID: $ISSUE_CONTEXT_ID. Type: $ISSUE_CONTEXT_TYPE', + 'run-1', + 'msg', + '/tmp', + 'main', + 'docs/', + 'context-data' + ); + expect(prompt).toBe('Issue: context-data. ID: $ISSUE_CONTEXT_ID. Type: $ISSUE_CONTEXT_TYPE'); + }); + + it('does not set contextSubstituted when only suffix-extended context vars are present', () => { + const { prompt, contextSubstituted } = substituteWorkflowVariables( + 'Path: $CONTEXT_FILE', + 'run-1', + 'msg', + '/tmp', + 'main', + 'docs/', + 'context-data' + ); + // $CONTEXT_FILE is not a context variable — should be left untouched + expect(prompt).toBe('Path: $CONTEXT_FILE'); + expect(contextSubstituted).toBe(false); + }); + it('clears context variables when issueContext is undefined', () => { const { prompt, contextSubstituted } = substituteWorkflowVariables( 'Context: $CONTEXT here', diff --git a/packages/workflows/src/executor-shared.ts b/packages/workflows/src/executor-shared.ts index e1978ae1..255895a5 100644 --- a/packages/workflows/src/executor-shared.ts +++ b/packages/workflows/src/executor-shared.ts @@ -242,7 +242,8 @@ export async function loadCommandPrompt( // ─── Variable Substitution ─────────────────────────────────────────────────── /** Pattern string for context variables - used to create fresh regex instances */ -export const CONTEXT_VAR_PATTERN_STR = '\\$(?:CONTEXT|EXTERNAL_CONTEXT|ISSUE_CONTEXT)'; +export const CONTEXT_VAR_PATTERN_STR = + '\\$(?:CONTEXT|EXTERNAL_CONTEXT|ISSUE_CONTEXT)(?![A-Za-z0-9_])'; /** * Substitute workflow variables in a prompt.