mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 16:39:42 +02:00
fix(terminal): linear-time link-provider regex; always allow blob workers in CSP
cmdPattern's empty-matchable unbounded arg group backtracked exponentially on wrapped heredoc/table lines — hovering one froze the tab for minutes. Non-empty tokens + bounded reps make it O(n); regression test extracts the shipped patterns and pins timing on the real killer shapes. worker-src 'self' blob: is now unconditional so terminal-ui's _safeYield tick worker (throttling escape) isn't CSP-blocked on non-gesture installs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @fileoverview Tests for Ralph loop prompt construction
|
||||
*
|
||||
* Verifies buildRalphLoopPrompt() output, and that the RALPH_STATUS contract
|
||||
* embedded in the prompt stays in sync with what RalphStatusParser parses.
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildRalphLoopPrompt, RALPH_STATUS_CONTRACT } from '../src/prompts/ralph.js';
|
||||
import { RalphStatusParser } from '../src/ralph-status-parser.js';
|
||||
|
||||
describe('buildRalphLoopPrompt', () => {
|
||||
const baseOptions = {
|
||||
taskDescription: 'Add CRUD endpoints for todos',
|
||||
completionPhrase: 'COMPLETE',
|
||||
hasPlan: false,
|
||||
};
|
||||
|
||||
it('starts with the task description', () => {
|
||||
const prompt = buildRalphLoopPrompt(baseOptions);
|
||||
|
||||
expect(prompt.startsWith('Add CRUD endpoints for todos\n\n---\n\n')).toBe(true);
|
||||
});
|
||||
|
||||
it('embeds the completion phrase in the completion criteria', () => {
|
||||
const prompt = buildRalphLoopPrompt({ ...baseOptions, completionPhrase: 'ALL_DONE' });
|
||||
|
||||
expect(prompt).toContain('<promise>ALL_DONE</promise>');
|
||||
expect(prompt).toContain('## Completion Criteria');
|
||||
});
|
||||
|
||||
it('includes the task plan section only when a plan exists', () => {
|
||||
const withPlan = buildRalphLoopPrompt({ ...baseOptions, hasPlan: true });
|
||||
const withoutPlan = buildRalphLoopPrompt(baseOptions);
|
||||
|
||||
expect(withPlan).toContain('## Task Plan');
|
||||
expect(withPlan).toContain('@fix_plan.md');
|
||||
expect(withoutPlan).not.toContain('## Task Plan');
|
||||
});
|
||||
|
||||
it('always appends the RALPH_STATUS contract', () => {
|
||||
const prompt = buildRalphLoopPrompt(baseOptions);
|
||||
|
||||
expect(prompt).toContain(RALPH_STATUS_CONTRACT);
|
||||
expect(prompt).toContain('---RALPH_STATUS---');
|
||||
expect(prompt).toContain('---END_RALPH_STATUS---');
|
||||
});
|
||||
|
||||
it('documents every field RalphStatusParser expects', () => {
|
||||
for (const field of [
|
||||
'STATUS: IN_PROGRESS | COMPLETE | BLOCKED',
|
||||
'TASKS_COMPLETED_THIS_LOOP: <number>',
|
||||
'FILES_MODIFIED: <number>',
|
||||
'TESTS_STATUS: PASSING | FAILING | NOT_RUN',
|
||||
'WORK_TYPE: IMPLEMENTATION | TESTING | DOCUMENTATION | REFACTORING',
|
||||
'EXIT_SIGNAL: false | true',
|
||||
'RECOMMENDATION:',
|
||||
]) {
|
||||
expect(RALPH_STATUS_CONTRACT).toContain(field);
|
||||
}
|
||||
});
|
||||
|
||||
it('teaches a block format that RalphStatusParser actually parses', () => {
|
||||
// A response following the contract to the letter
|
||||
const conformingBlock = [
|
||||
'---RALPH_STATUS---',
|
||||
'STATUS: IN_PROGRESS',
|
||||
'TASKS_COMPLETED_THIS_LOOP: 2',
|
||||
'FILES_MODIFIED: 5',
|
||||
'TESTS_STATUS: PASSING',
|
||||
'WORK_TYPE: IMPLEMENTATION',
|
||||
'EXIT_SIGNAL: false',
|
||||
'RECOMMENDATION: Continue with the next endpoint',
|
||||
'---END_RALPH_STATUS---',
|
||||
];
|
||||
|
||||
const parser = new RalphStatusParser();
|
||||
for (const line of conformingBlock) {
|
||||
parser.processLine(line);
|
||||
}
|
||||
|
||||
const block = parser.lastStatusBlock;
|
||||
expect(block).not.toBeNull();
|
||||
expect(block?.status).toBe('IN_PROGRESS');
|
||||
expect(block?.tasksCompletedThisLoop).toBe(2);
|
||||
expect(block?.filesModified).toBe(5);
|
||||
expect(block?.testsStatus).toBe('PASSING');
|
||||
expect(block?.workType).toBe('IMPLEMENTATION');
|
||||
expect(block?.exitSignal).toBe(false);
|
||||
expect(block?.recommendation).toBe('Continue with the next endpoint');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user