397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
3.0 KiB
JavaScript
78 lines
3.0 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { buildReminder } from './enforce-prompt-injection.mjs';
|
|
|
|
describe('enforce-prompt-injection / buildReminder', () => {
|
|
it('always includes the coverage-first-line rule', () => {
|
|
const txt = buildReminder({ classification: null, recentFlags: [] });
|
|
expect(txt).toMatch(/First line of your response MUST be/);
|
|
expect(txt).toMatch(/coverage:\s*<channel>:<id>/);
|
|
});
|
|
|
|
it('includes classifier output when present', () => {
|
|
const txt = buildReminder({
|
|
classification: { task_type: 'feature', confidence: 0.85, recommended_node: '#19', recommended_chain: 'L13' },
|
|
recentFlags: [],
|
|
});
|
|
expect(txt).toMatch(/task_type=feature/);
|
|
expect(txt).toMatch(/confidence=0\.85/);
|
|
expect(txt).toMatch(/#19/);
|
|
expect(txt).toMatch(/L13/);
|
|
});
|
|
|
|
it('mentions plan requirement for feature/bugfix/refactor/cleanup', () => {
|
|
for (const t of ['feature', 'bugfix', 'refactor', 'cleanup']) {
|
|
const txt = buildReminder({
|
|
classification: { task_type: t, confidence: 0.7 },
|
|
recentFlags: [],
|
|
});
|
|
expect(txt).toMatch(/Plan required/);
|
|
}
|
|
});
|
|
|
|
it('omits plan requirement for conversation/question', () => {
|
|
const txt = buildReminder({
|
|
classification: { task_type: 'question', confidence: 0.9 },
|
|
recentFlags: [],
|
|
});
|
|
expect(txt).not.toMatch(/Plan required/);
|
|
});
|
|
|
|
it('surfaces recent rationalization flags (up to 3)', () => {
|
|
const txt = buildReminder({
|
|
classification: null,
|
|
recentFlags: [
|
|
{ kind: 'skipped-plan', evidence: 'too simple' },
|
|
{ kind: 'single-coverage-drift', evidence: 'TDD coverage used for memory sync' },
|
|
{ kind: 'weak-test', evidence: '1 expect' },
|
|
{ kind: 'commit-without-tests', evidence: 'production edit without test' },
|
|
],
|
|
});
|
|
expect(txt).toMatch(/Previous turn flagged/);
|
|
// Last 3 should appear, first one should NOT
|
|
expect(txt).toMatch(/single-coverage-drift/);
|
|
expect(txt).toMatch(/weak-test/);
|
|
expect(txt).toMatch(/commit-without-tests/);
|
|
expect(txt).not.toMatch(/skipped-plan/);
|
|
});
|
|
|
|
it('notes detected override phrase + suppressed rule keys', () => {
|
|
const txt = buildReminder({
|
|
classification: null,
|
|
recentFlags: [],
|
|
override: { phrase: 'срочно', suppresses: ['verify-before-push', 'tdd-gate'] },
|
|
});
|
|
expect(txt).toMatch(/Override phrase detected/);
|
|
expect(txt).toMatch(/срочно/);
|
|
expect(txt).toMatch(/verify-before-push/);
|
|
});
|
|
|
|
it('does NOT advertise dead override-vocabulary phrases (v4 stub — 1A 2026-05-31)', () => {
|
|
const txt = buildReminder({ classification: null, recentFlags: [] });
|
|
// findOverride/loadOverrideVocab — заглушки (vocab removed in v4); реклама фраз
|
|
// вводила в заблуждение (фразы не работают). Баннер убран.
|
|
expect(txt).not.toMatch(/Override vocabulary/);
|
|
expect(txt).not.toMatch(/без скилов/);
|
|
expect(txt).not.toMatch(/ремонт инфраструктуры/);
|
|
});
|
|
});
|