Skip to content

Commit b2fc2f6

Browse files
author
catlog22
committed
feat: implement ignore patterns and extension filters in CodexLens
- Added tests to ensure loading of ignore patterns and extension filters from settings. - Implemented functionality to respect ignore patterns and extension filters during file indexing. - Created integration tests for CodexLens ignore-pattern configuration routes. - Added a new AdvancedTab component with tests for managing ignore patterns and extension filters. - Established a comprehensive branding naming system for the Maestro project, including guidelines for package names, CLI commands, and directory structure.
1 parent 3341a2e commit b2fc2f6

33 files changed

Lines changed: 1489 additions & 69 deletions

File tree

.codex/skills/team-planex/SKILL.md

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -502,40 +502,3 @@ if (plannerAgent) {
502502
| `check` / `status` | Show progress: planned / executing / completed / failed counts |
503503
| `resume` / `continue` | Re-enter loop from Phase 2 |
504504

505-
506-
---
507-
508-
## Coordinator Role Constraints (Main Agent)
509-
510-
**CRITICAL**: The coordinator (main agent executing this skill) is responsible for **orchestration only**, NOT implementation.
511-
512-
15. **Coordinator Does NOT Execute Code**: The main agent MUST NOT write, modify, or implement any code directly. All implementation work is delegated to spawned team agents. The coordinator only:
513-
- Spawns agents with task assignments
514-
- Waits for agent callbacks
515-
- Merges results and coordinates workflow
516-
- Manages workflow transitions between phases
517-
518-
16. **Patient Waiting is Mandatory**: Agent execution takes significant time (typically 10-30 minutes per phase, sometimes longer). The coordinator MUST:
519-
- Wait patiently for `wait()` calls to complete
520-
- NOT skip workflow steps due to perceived delays
521-
- NOT assume agents have failed just because they're taking time
522-
- Trust the timeout mechanisms defined in the skill
523-
524-
17. **Use send_input for Clarification**: When agents need guidance or appear stuck, the coordinator MUST:
525-
- Use `send_input()` to ask questions or provide clarification
526-
- NOT skip the agent or move to next phase prematurely
527-
- Give agents opportunity to respond before escalating
528-
- Example: `send_input({ id: agent_id, message: "Please provide status update or clarify blockers" })`
529-
530-
18. **No Workflow Shortcuts**: The coordinator MUST NOT:
531-
- Skip phases or stages defined in the workflow
532-
- Bypass required approval or review steps
533-
- Execute dependent tasks before prerequisites complete
534-
- Assume task completion without explicit agent callback
535-
- Make up or fabricate agent results
536-
537-
19. **Respect Long-Running Processes**: This is a complex multi-agent workflow that requires patience:
538-
- Total execution time may range from 30-90 minutes or longer
539-
- Each phase may take 10-30 minutes depending on complexity
540-
- The coordinator must remain active and attentive throughout the entire process
541-
- Do not terminate or skip steps due to time concerns
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest';
2+
import { fireEvent } from '@testing-library/react';
3+
import { render, screen, waitFor } from '@/test/i18n';
4+
import { AdvancedTab } from './AdvancedTab';
5+
6+
vi.mock('@/hooks', async (importOriginal) => {
7+
const actual = await importOriginal<typeof import('@/hooks')>();
8+
return {
9+
...actual,
10+
useCodexLensEnv: vi.fn(),
11+
useUpdateCodexLensEnv: vi.fn(),
12+
useCodexLensIgnorePatterns: vi.fn(),
13+
useUpdateIgnorePatterns: vi.fn(),
14+
useNotifications: vi.fn(),
15+
};
16+
});
17+
18+
import {
19+
useCodexLensEnv,
20+
useUpdateCodexLensEnv,
21+
useCodexLensIgnorePatterns,
22+
useUpdateIgnorePatterns,
23+
useNotifications,
24+
} from '@/hooks';
25+
26+
const mockRefetchEnv = vi.fn().mockResolvedValue(undefined);
27+
const mockRefetchPatterns = vi.fn().mockResolvedValue(undefined);
28+
const mockUpdateEnv = vi.fn().mockResolvedValue({ success: true, message: 'Saved' });
29+
const mockUpdatePatterns = vi.fn().mockResolvedValue({
30+
success: true,
31+
patterns: ['dist', 'frontend/dist'],
32+
extensionFilters: ['*.min.js', 'frontend/skip.ts'],
33+
defaults: {
34+
patterns: ['dist', 'build'],
35+
extensionFilters: ['*.min.js'],
36+
},
37+
});
38+
const mockToastSuccess = vi.fn();
39+
const mockToastError = vi.fn();
40+
41+
function setupDefaultMocks() {
42+
vi.mocked(useCodexLensEnv).mockReturnValue({
43+
data: { success: true, env: {}, settings: {}, raw: '', path: '~/.codexlens/.env' },
44+
raw: '',
45+
env: {},
46+
settings: {},
47+
isLoading: false,
48+
error: null,
49+
refetch: mockRefetchEnv,
50+
});
51+
52+
vi.mocked(useUpdateCodexLensEnv).mockReturnValue({
53+
updateEnv: mockUpdateEnv,
54+
isUpdating: false,
55+
error: null,
56+
});
57+
58+
vi.mocked(useCodexLensIgnorePatterns).mockReturnValue({
59+
data: {
60+
success: true,
61+
patterns: ['dist', 'coverage'],
62+
extensionFilters: ['*.min.js', '*.map'],
63+
defaults: {
64+
patterns: ['dist', 'build', 'coverage'],
65+
extensionFilters: ['*.min.js', '*.map'],
66+
},
67+
},
68+
patterns: ['dist', 'coverage'],
69+
extensionFilters: ['*.min.js', '*.map'],
70+
defaults: {
71+
patterns: ['dist', 'build', 'coverage'],
72+
extensionFilters: ['*.min.js', '*.map'],
73+
},
74+
isLoading: false,
75+
error: null,
76+
refetch: mockRefetchPatterns,
77+
});
78+
79+
vi.mocked(useUpdateIgnorePatterns).mockReturnValue({
80+
updatePatterns: mockUpdatePatterns,
81+
isUpdating: false,
82+
error: null,
83+
});
84+
85+
vi.mocked(useNotifications).mockReturnValue({
86+
success: mockToastSuccess,
87+
error: mockToastError,
88+
} as ReturnType<typeof useNotifications>);
89+
}
90+
91+
describe('AdvancedTab', () => {
92+
beforeEach(() => {
93+
vi.clearAllMocks();
94+
setupDefaultMocks();
95+
});
96+
97+
it('renders existing filter configuration', () => {
98+
render(<AdvancedTab enabled={true} />);
99+
100+
expect(screen.getByLabelText(/Ignored directories \/ paths/i)).toHaveValue('dist\ncoverage');
101+
expect(screen.getByLabelText(/Skipped files \/ globs/i)).toHaveValue('*.min.js\n*.map');
102+
expect(screen.getByText(/Directory filters: 2/i)).toBeInTheDocument();
103+
expect(screen.getByText(/File filters: 2/i)).toBeInTheDocument();
104+
});
105+
106+
it('saves parsed filter configuration', async () => {
107+
render(<AdvancedTab enabled={true} />);
108+
109+
const ignorePatternsInput = screen.getByLabelText(/Ignored directories \/ paths/i);
110+
const extensionFiltersInput = screen.getByLabelText(/Skipped files \/ globs/i);
111+
112+
fireEvent.change(ignorePatternsInput, { target: { value: 'dist,\nfrontend/dist' } });
113+
fireEvent.change(extensionFiltersInput, { target: { value: '*.min.js,\nfrontend/skip.ts' } });
114+
fireEvent.click(screen.getByRole('button', { name: /Save filters/i }));
115+
116+
await waitFor(() => {
117+
expect(mockUpdatePatterns).toHaveBeenCalledWith({
118+
patterns: ['dist', 'frontend/dist'],
119+
extensionFilters: ['*.min.js', 'frontend/skip.ts'],
120+
});
121+
});
122+
expect(mockRefetchPatterns).toHaveBeenCalled();
123+
});
124+
125+
it('restores default filter values before saving', async () => {
126+
render(<AdvancedTab enabled={true} />);
127+
128+
fireEvent.click(screen.getByRole('button', { name: /Restore defaults/i }));
129+
130+
expect(screen.getByLabelText(/Ignored directories \/ paths/i)).toHaveValue('dist\nbuild\ncoverage');
131+
expect(screen.getByLabelText(/Skipped files \/ globs/i)).toHaveValue('*.min.js\n*.map');
132+
133+
fireEvent.click(screen.getByRole('button', { name: /Save filters/i }));
134+
135+
await waitFor(() => {
136+
expect(mockUpdatePatterns).toHaveBeenCalledWith({
137+
patterns: ['dist', 'build', 'coverage'],
138+
extensionFilters: ['*.min.js', '*.map'],
139+
});
140+
});
141+
});
142+
143+
it('blocks invalid filter entries before saving', async () => {
144+
render(<AdvancedTab enabled={true} />);
145+
146+
fireEvent.change(screen.getByLabelText(/Ignored directories \/ paths/i), {
147+
target: { value: 'bad pattern!' },
148+
});
149+
fireEvent.click(screen.getByRole('button', { name: /Save filters/i }));
150+
151+
expect(mockUpdatePatterns).not.toHaveBeenCalled();
152+
expect(screen.getByText(/Invalid ignore patterns/i)).toBeInTheDocument();
153+
});
154+
});

0 commit comments

Comments
 (0)