mirror of
https://github.com/coleam00/Archon
synced 2026-04-21 13:37:41 +00:00
fix(workflows): add word boundary to context variable substitution regex (#1256)
* fix(workflows): add word boundary to context variable substitution regex (#1112) Variable substitution for $CONTEXT, $EXTERNAL_CONTEXT, and $ISSUE_CONTEXT was matching as a prefix of longer identifiers like $CONTEXT_FILE, silently corrupting bash node scripts. Added negative lookahead (?![A-Za-z0-9_]) to CONTEXT_VAR_PATTERN_STR so only exact variable names are substituted. Changes: - Add negative lookahead to CONTEXT_VAR_PATTERN_STR regex in executor-shared.ts - Add regression test for prefix-match boundary case Fixes #1112 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(workflows): add missing boundary cases for context variable substitution Add three new test cases that complete coverage of the word-boundary fix from #1112: $ISSUE_CONTEXT with suffix variants, $ISSUE_CONTEXT with multiple suffixes, and contextSubstituted=false for suffix-only prompts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
df828594d7
commit
bed36ca4ad
2 changed files with 46 additions and 1 deletions
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue