397777089e
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
93 lines
3.0 KiB
JavaScript
93 lines
3.0 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { decide } from './enforce-branch-switch.mjs';
|
|
|
|
describe('enforce-branch-switch / decide', () => {
|
|
it('allows non-Bash tools', () => {
|
|
expect(decide({ toolName: 'Edit', command: '' }).block).toBe(false);
|
|
});
|
|
|
|
it('allows non-git Bash commands', () => {
|
|
expect(decide({ toolName: 'Bash', command: 'ls -la', actualBranch: 'feat/x', expectedBranch: 'main' }).block).toBe(false);
|
|
});
|
|
|
|
it('allows git status / git log (read-only)', () => {
|
|
expect(decide({ toolName: 'Bash', command: 'git status', actualBranch: 'feat/x', expectedBranch: 'main' }).block).toBe(false);
|
|
});
|
|
|
|
it('blocks git commit when actual != expected', () => {
|
|
const r = decide({
|
|
toolName: 'Bash',
|
|
command: 'git commit -m "x"',
|
|
actualBranch: 'feat/supplier',
|
|
expectedBranch: 'main',
|
|
assistantText: 'some random text',
|
|
});
|
|
expect(r.block).toBe(true);
|
|
expect(r.message).toMatch(/feat\/supplier.*main/);
|
|
});
|
|
|
|
it('blocks git push on wrong branch', () => {
|
|
const r = decide({
|
|
toolName: 'Bash',
|
|
command: 'LEFTHOOK=0 git push origin main',
|
|
actualBranch: 'feat/other',
|
|
expectedBranch: 'main',
|
|
assistantText: '',
|
|
});
|
|
expect(r.block).toBe(true);
|
|
});
|
|
|
|
it('allows when BRANCH-SWITCH-CONFIRMED marker present in assistant text', () => {
|
|
const r = decide({
|
|
toolName: 'Bash',
|
|
command: 'git commit -m "x"',
|
|
actualBranch: 'feat/x',
|
|
expectedBranch: 'main',
|
|
assistantText: 'BRANCH-SWITCH-CONFIRMED — продолжаю на feat/x по плану',
|
|
});
|
|
expect(r.block).toBe(false);
|
|
});
|
|
|
|
it('allows when RECOVERY-INTENT marker present', () => {
|
|
const r = decide({
|
|
toolName: 'Bash',
|
|
command: 'git cherry-pick abc123',
|
|
actualBranch: 'main',
|
|
expectedBranch: 'feat/x',
|
|
assistantText: 'RECOVERY-INTENT: cherry-pick после смены ветки чужой сессией',
|
|
});
|
|
expect(r.block).toBe(false);
|
|
});
|
|
|
|
it('allows when override phrase present', () => {
|
|
const r = decide({
|
|
toolName: 'Bash',
|
|
command: 'git commit -m "x"',
|
|
actualBranch: 'feat/x',
|
|
expectedBranch: 'main',
|
|
assistantText: '',
|
|
override: { phrase: 'recovery', suppresses: ['branch-switch'] },
|
|
});
|
|
expect(r.block).toBe(false);
|
|
});
|
|
|
|
it('allows on match', () => {
|
|
const r = decide({
|
|
toolName: 'Bash',
|
|
command: 'git commit -m "x"',
|
|
actualBranch: 'main',
|
|
expectedBranch: 'main',
|
|
});
|
|
expect(r.block).toBe(false);
|
|
});
|
|
|
|
it('defaults expected to "main" if unset and matches when on main', () => {
|
|
expect(decide({ toolName: 'Bash', command: 'git commit', actualBranch: 'main', expectedBranch: '' }).block).toBe(false);
|
|
});
|
|
|
|
it('defaults expected to "main" if unset and blocks when on feature branch', () => {
|
|
const r = decide({ toolName: 'Bash', command: 'git commit', actualBranch: 'feat/x', expectedBranch: '' });
|
|
expect(r.block).toBe(true);
|
|
});
|
|
});
|