Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/parallel-execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export function detectTeammateTool() {
}

if (isNativeBinary(claudePath)) {
return { available: false, reason: 'Native binary detected - patching not supported', isNative: true };
// Native Claude Code binaries have built-in parallel execution via Task tool
return { available: true, method: 'native', isNative: true };
}

const cliContent = fs.readFileSync(claudePath, 'utf8');
Expand Down Expand Up @@ -151,7 +152,8 @@ export function enableTeammateTool() {
}

if (isNativeBinary(claudePath)) {
return { success: false, error: 'Native binary detected - patching not supported. TeammateTool patching only works with npm-installed Claude Code.' };
// Native binaries have built-in support, no patching needed
return { success: true, message: 'Native binary has built-in parallel execution support', alreadyEnabled: true };
}

// Backup original
Expand Down
2 changes: 1 addition & 1 deletion lib/presets.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export function listPresets() {
export function validateConfiguration(config) {
const errors = [];
const availableAgents = ['orchestrator', 'architect', 'backend', 'frontend', 'tester', 'reviewer', 'fixer', 'product-analyzer'];
const availableSkills = ['product-tracking', 'validation', 'testing', 'conversation', 'product-planning', 'deployment'];
const availableSkills = ['product-tracking', 'validation', 'testing', 'conversation', 'product-planning', 'deployment', 'research'];
const availableHooks = Object.keys(hookConfigurations);

// Always require orchestrator
Expand Down
14 changes: 8 additions & 6 deletions test/unit/parallel-execution.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ describe('Parallel Execution', () => {
expect(result.reason).toContain('binary not found');
});

it('should detect native Mach-O binary and skip patching', () => {
it('should detect native Mach-O binary as having built-in parallel support', () => {
// Native Claude Code binaries have built-in Task tool parallel execution
execSync.mockImplementation((cmd) => {
if (cmd.includes('npm root -g')) {
return '/usr/local/lib/node_modules\n';
Expand All @@ -64,8 +65,8 @@ describe('Parallel Execution', () => {

const result = detectTeammateTool();

expect(result.available).toBe(false);
expect(result.reason).toContain('Native binary');
expect(result.available).toBe(true);
expect(result.method).toBe('native');
expect(result.isNative).toBe(true);
});

Expand Down Expand Up @@ -157,7 +158,8 @@ describe('Parallel Execution', () => {
});

describe('enableTeammateTool', () => {
it('should reject native Mach-O binary', () => {
it('should report native Mach-O binary as already enabled', () => {
// Native binaries have built-in parallel support, no patching needed
execSync.mockImplementation((cmd) => {
if (cmd.includes('npm root -g')) {
return '/usr/local/lib/node_modules\n';
Expand All @@ -182,8 +184,8 @@ describe('Parallel Execution', () => {

const result = enableTeammateTool();

expect(result.success).toBe(false);
expect(result.error).toContain('Native binary');
expect(result.success).toBe(true);
expect(result.alreadyEnabled).toBe(true);
});

it('should create backup before patching', () => {
Expand Down
28 changes: 28 additions & 0 deletions test/unit/presets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,34 @@ describe('validateConfiguration', () => {
const result = validateConfiguration(config);
expect(result.valid).toBe(true);
});

it('should accept research skill (regression test)', () => {
// Regression test: research skill was in default preset but missing from availableSkills
const config = {
agents: ['orchestrator'],
skills: ['research'],
hooks: [],
gates: []
};

const result = validateConfiguration(config);
expect(result.valid).toBe(true);
expect(result.errors).not.toContain(expect.stringContaining('Invalid skills'));
});

it('default preset skills should all be valid', () => {
// Ensure all skills in the default preset pass validation
const config = {
agents: presets.default.agents,
skills: presets.default.skills,
hooks: presets.default.hooks,
gates: presets.default.gates
};

const result = validateConfiguration(config);
const skillErrors = result.errors.filter(e => e.includes('Invalid skills'));
expect(skillErrors).toHaveLength(0);
});
});

describe('generateHooksConfig', () => {
Expand Down
Loading