aigent-team 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +253 -0
  3. package/dist/chunk-N3RYHWTR.js +267 -0
  4. package/dist/cli.js +576 -0
  5. package/dist/index.d.ts +234 -0
  6. package/dist/index.js +27 -0
  7. package/package.json +67 -0
  8. package/templates/shared/git-workflow.md +44 -0
  9. package/templates/shared/project-conventions.md +48 -0
  10. package/templates/teams/ba/agent.yaml +25 -0
  11. package/templates/teams/ba/references/acceptance-criteria.md +87 -0
  12. package/templates/teams/ba/references/api-contract-design.md +110 -0
  13. package/templates/teams/ba/references/requirements-analysis.md +83 -0
  14. package/templates/teams/ba/references/user-story-mapping.md +73 -0
  15. package/templates/teams/ba/skill.md +85 -0
  16. package/templates/teams/be/agent.yaml +34 -0
  17. package/templates/teams/be/conventions.md +102 -0
  18. package/templates/teams/be/references/api-design.md +91 -0
  19. package/templates/teams/be/references/async-processing.md +86 -0
  20. package/templates/teams/be/references/auth-security.md +58 -0
  21. package/templates/teams/be/references/caching.md +79 -0
  22. package/templates/teams/be/references/database.md +65 -0
  23. package/templates/teams/be/references/error-handling.md +106 -0
  24. package/templates/teams/be/references/observability.md +83 -0
  25. package/templates/teams/be/references/review-checklist.md +50 -0
  26. package/templates/teams/be/references/testing.md +100 -0
  27. package/templates/teams/be/review-checklist.md +54 -0
  28. package/templates/teams/be/skill.md +71 -0
  29. package/templates/teams/devops/agent.yaml +35 -0
  30. package/templates/teams/devops/conventions.md +133 -0
  31. package/templates/teams/devops/references/ci-cd.md +218 -0
  32. package/templates/teams/devops/references/cost-optimization.md +218 -0
  33. package/templates/teams/devops/references/disaster-recovery.md +199 -0
  34. package/templates/teams/devops/references/docker.md +237 -0
  35. package/templates/teams/devops/references/infrastructure-as-code.md +238 -0
  36. package/templates/teams/devops/references/kubernetes.md +397 -0
  37. package/templates/teams/devops/references/monitoring.md +224 -0
  38. package/templates/teams/devops/references/review-checklist.md +149 -0
  39. package/templates/teams/devops/references/security.md +225 -0
  40. package/templates/teams/devops/review-checklist.md +72 -0
  41. package/templates/teams/devops/skill.md +131 -0
  42. package/templates/teams/fe/agent.yaml +28 -0
  43. package/templates/teams/fe/conventions.md +80 -0
  44. package/templates/teams/fe/references/accessibility.md +92 -0
  45. package/templates/teams/fe/references/component-architecture.md +87 -0
  46. package/templates/teams/fe/references/css-styling.md +89 -0
  47. package/templates/teams/fe/references/forms.md +73 -0
  48. package/templates/teams/fe/references/performance.md +104 -0
  49. package/templates/teams/fe/references/review-checklist.md +51 -0
  50. package/templates/teams/fe/references/security.md +90 -0
  51. package/templates/teams/fe/references/state-management.md +117 -0
  52. package/templates/teams/fe/references/testing.md +112 -0
  53. package/templates/teams/fe/review-checklist.md +53 -0
  54. package/templates/teams/fe/skill.md +68 -0
  55. package/templates/teams/lead/agent.yaml +18 -0
  56. package/templates/teams/lead/references/cross-team-coordination.md +68 -0
  57. package/templates/teams/lead/references/quality-gates.md +64 -0
  58. package/templates/teams/lead/references/task-decomposition.md +69 -0
  59. package/templates/teams/lead/skill.md +83 -0
  60. package/templates/teams/qa/agent.yaml +32 -0
  61. package/templates/teams/qa/conventions.md +130 -0
  62. package/templates/teams/qa/references/ci-integration.md +337 -0
  63. package/templates/teams/qa/references/e2e-testing.md +292 -0
  64. package/templates/teams/qa/references/mocking.md +249 -0
  65. package/templates/teams/qa/references/performance-testing.md +288 -0
  66. package/templates/teams/qa/references/review-checklist.md +143 -0
  67. package/templates/teams/qa/references/security-testing.md +271 -0
  68. package/templates/teams/qa/references/test-data.md +275 -0
  69. package/templates/teams/qa/references/test-strategy.md +192 -0
  70. package/templates/teams/qa/review-checklist.md +53 -0
  71. package/templates/teams/qa/skill.md +131 -0
@@ -0,0 +1,292 @@
1
+ # E2E Testing Reference
2
+
3
+ ## Page Object Model
4
+
5
+ Encapsulate page interactions behind a stable API. Tests read like user stories;
6
+ selectors and waits live in one place.
7
+
8
+ ### Structure
9
+
10
+ ```
11
+ e2e/
12
+ pages/
13
+ login.page.ts
14
+ dashboard.page.ts
15
+ checkout.page.ts
16
+ fixtures/
17
+ auth.fixture.ts
18
+ specs/
19
+ checkout.spec.ts
20
+ ```
21
+
22
+ ### Page Object Example (Playwright)
23
+
24
+ ```typescript
25
+ // e2e/pages/checkout.page.ts
26
+ import { type Page, type Locator } from '@playwright/test';
27
+
28
+ export class CheckoutPage {
29
+ private readonly cartItems: Locator;
30
+ private readonly promoCodeInput: Locator;
31
+ private readonly applyPromoButton: Locator;
32
+ private readonly totalPrice: Locator;
33
+ private readonly placeOrderButton: Locator;
34
+
35
+ constructor(private readonly page: Page) {
36
+ this.cartItems = page.getByRole('list', { name: 'Cart items' }).getByRole('listitem');
37
+ this.promoCodeInput = page.getByLabel('Promo code');
38
+ this.applyPromoButton = page.getByRole('button', { name: 'Apply' });
39
+ this.totalPrice = page.getByTestId('total-price');
40
+ this.placeOrderButton = page.getByRole('button', { name: 'Place order' });
41
+ }
42
+
43
+ async applyPromoCode(code: string) {
44
+ await this.promoCodeInput.fill(code);
45
+ await this.applyPromoButton.click();
46
+ }
47
+
48
+ async placeOrder() {
49
+ await this.placeOrderButton.click();
50
+ await this.page.waitForURL('**/confirmation');
51
+ }
52
+
53
+ async getTotal(): Promise<string> {
54
+ return this.totalPrice.textContent() ?? '';
55
+ }
56
+
57
+ async getItemCount(): Promise<number> {
58
+ return this.cartItems.count();
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Test Using Page Object
64
+
65
+ ```typescript
66
+ // e2e/specs/checkout.spec.ts
67
+ import { test, expect } from '@playwright/test';
68
+ import { CheckoutPage } from '../pages/checkout.page';
69
+
70
+ test.describe('Checkout', () => {
71
+ let checkout: CheckoutPage;
72
+
73
+ test.beforeEach(async ({ page }) => {
74
+ // Seed cart via API — never through UI
75
+ await page.request.post('/api/test/seed-cart', {
76
+ data: { items: [{ sku: 'WIDGET-1', qty: 2 }] },
77
+ });
78
+ await page.goto('/checkout');
79
+ checkout = new CheckoutPage(page);
80
+ });
81
+
82
+ test('applies promo code and updates total', async () => {
83
+ await checkout.applyPromoCode('SAVE20');
84
+ await expect(checkout.getTotal()).resolves.toContain('$16.00');
85
+ });
86
+ });
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Element Selection Priority
92
+
93
+ Use the most accessible selector available. Order of preference:
94
+
95
+ 1. **`getByRole`** — matches what assistive technology sees.
96
+ `page.getByRole('button', { name: 'Submit' })`
97
+ 2. **`getByLabel`** — form fields with proper labels.
98
+ `page.getByLabel('Email address')`
99
+ 3. **`getByPlaceholder`** — fallback for unlabelled inputs.
100
+ 4. **`getByText`** — visible text content.
101
+ 5. **`getByTestId`** — last resort; requires `data-testid` attribute.
102
+
103
+ Never use CSS selectors or XPath tied to DOM structure. They break on
104
+ refactors and provide no accessibility signal.
105
+
106
+ ---
107
+
108
+ ## Wait Strategy
109
+
110
+ ### Rule: Never Use Fixed Delays
111
+
112
+ ```typescript
113
+ // BAD — arbitrary delay, still flaky
114
+ await page.waitForTimeout(3000);
115
+
116
+ // GOOD — wait for specific condition
117
+ await page.waitForSelector('[data-loaded="true"]');
118
+ await expect(page.getByText('Order confirmed')).toBeVisible();
119
+ ```
120
+
121
+ ### Playwright Auto-Waiting
122
+
123
+ Playwright auto-waits for elements to be actionable before interacting.
124
+ Lean on this. Additional explicit waits for:
125
+
126
+ - **Navigation**: `await page.waitForURL('**/dashboard')`
127
+ - **Network idle**: `await page.waitForLoadState('networkidle')` (use
128
+ sparingly — prefer waiting for specific elements)
129
+ - **API response**: `await page.waitForResponse(resp => resp.url().includes('/api/orders') && resp.status() === 200)`
130
+ - **Custom condition**: `await expect(locator).toHaveCount(3)`
131
+
132
+ ### Timeout Configuration
133
+
134
+ ```typescript
135
+ // playwright.config.ts
136
+ export default defineConfig({
137
+ timeout: 30_000, // per-test timeout
138
+ expect: {
139
+ timeout: 5_000, // per-assertion timeout
140
+ },
141
+ use: {
142
+ actionTimeout: 10_000, // per-action timeout (click, fill, etc.)
143
+ navigationTimeout: 15_000,
144
+ },
145
+ });
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Test Data Setup via API
151
+
152
+ Never create test data through the UI. It is slow, brittle, and couples
153
+ tests to unrelated pages.
154
+
155
+ ### Pattern: API Seeding
156
+
157
+ ```typescript
158
+ test.beforeEach(async ({ page }) => {
159
+ // Create user and get auth token
160
+ const res = await page.request.post('/api/test/users', {
161
+ data: { email: 'qa@test.com', role: 'admin' },
162
+ });
163
+ const { token } = await res.json();
164
+
165
+ // Set auth cookie/header
166
+ await page.context().addCookies([{
167
+ name: 'auth_token',
168
+ value: token,
169
+ domain: 'localhost',
170
+ path: '/',
171
+ }]);
172
+ });
173
+ ```
174
+
175
+ ### Pattern: Storage State for Auth
176
+
177
+ ```typescript
178
+ // e2e/fixtures/auth.fixture.ts — run once, reuse across tests
179
+ import { test as setup } from '@playwright/test';
180
+
181
+ setup('authenticate', async ({ page }) => {
182
+ await page.goto('/login');
183
+ await page.getByLabel('Email').fill('admin@test.com');
184
+ await page.getByLabel('Password').fill('test-password');
185
+ await page.getByRole('button', { name: 'Sign in' }).click();
186
+ await page.waitForURL('**/dashboard');
187
+ await page.context().storageState({ path: '.auth/admin.json' });
188
+ });
189
+
190
+ // playwright.config.ts
191
+ export default defineConfig({
192
+ projects: [
193
+ { name: 'setup', testMatch: /auth\.fixture\.ts/ },
194
+ {
195
+ name: 'tests',
196
+ dependencies: ['setup'],
197
+ use: { storageState: '.auth/admin.json' },
198
+ },
199
+ ],
200
+ });
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Parallel Execution Safety
206
+
207
+ Playwright runs tests in parallel by default. Tests must be fully isolated:
208
+
209
+ - **No shared database rows.** Each test creates its own data with unique IDs.
210
+ - **No shared files.** Use temp directories or unique filenames.
211
+ - **No port conflicts.** Use dynamic ports or separate server instances.
212
+ - **No sequential assumptions.** Never rely on test execution order.
213
+
214
+ If a test cannot be parallelised (e.g., it modifies global settings), mark it:
215
+
216
+ ```typescript
217
+ test.describe.serial('Admin settings', () => {
218
+ // These tests run sequentially within this describe block
219
+ });
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Flakiness Prevention
225
+
226
+ ### Common Causes and Fixes
227
+
228
+ | Cause | Detection | Fix |
229
+ |---|---|---|
230
+ | Race condition (element not ready) | Passes locally, fails in CI | Replace `waitForTimeout` with explicit waits |
231
+ | Shared test state | Fails when run order changes | Isolate data per test |
232
+ | Animation interfering with click | Intermittent click misses | Disable animations in test config |
233
+ | Viewport-dependent layout | Fails on different screen sizes | Set fixed viewport in config |
234
+ | Third-party dependency | Flaky external API | Mock external services in E2E |
235
+ | Time-dependent logic | Fails at midnight/month-end | Mock clock or use stable test dates |
236
+
237
+ ### Playwright Anti-Flake Config
238
+
239
+ ```typescript
240
+ // playwright.config.ts
241
+ export default defineConfig({
242
+ retries: process.env.CI ? 2 : 0, // Retries hide flakiness locally
243
+ use: {
244
+ video: 'retain-on-failure',
245
+ screenshot: 'only-on-failure',
246
+ trace: 'retain-on-failure',
247
+ },
248
+ });
249
+ ```
250
+
251
+ ### Flakiness Detection
252
+
253
+ Run suspect tests in a loop locally before merging:
254
+
255
+ ```bash
256
+ npx playwright test checkout.spec.ts --repeat-each=20
257
+ ```
258
+
259
+ If it fails once in 20, it is flaky. Fix before merging.
260
+
261
+ ---
262
+
263
+ ## Screenshot and Trace on Failure
264
+
265
+ Always capture artifacts on failure for debugging:
266
+
267
+ ```typescript
268
+ // playwright.config.ts
269
+ export default defineConfig({
270
+ use: {
271
+ screenshot: 'only-on-failure',
272
+ video: 'retain-on-failure',
273
+ trace: 'retain-on-failure',
274
+ },
275
+ outputDir: 'test-results/',
276
+ });
277
+ ```
278
+
279
+ In CI, upload the `test-results/` directory as a build artifact:
280
+
281
+ ```yaml
282
+ # GitHub Actions
283
+ - uses: actions/upload-artifact@v4
284
+ if: failure()
285
+ with:
286
+ name: playwright-results
287
+ path: test-results/
288
+ retention-days: 7
289
+ ```
290
+
291
+ Traces can be viewed at https://trace.playwright.dev — share the link in
292
+ bug reports for full reproduction context.
@@ -0,0 +1,249 @@
1
+ # Mocking Reference
2
+
3
+ ## Core Rule: Mock at System Boundaries Only
4
+
5
+ A mock replaces something your code *cannot control* during a test:
6
+
7
+ - **HTTP requests** to external services
8
+ - **System clock** (`Date.now`, timers)
9
+ - **Randomness** (`Math.random`, `crypto.randomUUID`)
10
+ - **File system** (only when testing I/O behaviour, not business logic)
11
+
12
+ Everything else — internal modules, utility functions, class methods — should
13
+ use the real implementation. If you feel the need to mock an internal module,
14
+ it is a design smell: extract an interface and inject the dependency.
15
+
16
+ ### Why Not Mock Internals?
17
+
18
+ ```typescript
19
+ // BAD — mocking internal module
20
+ vi.mock('../utils/calculateTax', () => ({
21
+ calculateTax: vi.fn(() => 5.00),
22
+ }));
23
+
24
+ test('order total includes tax', () => {
25
+ // This test proves nothing. You mocked the very thing
26
+ // that computes the value you're asserting on.
27
+ expect(getOrderTotal(items)).toBe(105.00);
28
+ });
29
+
30
+ // GOOD — test the real calculation
31
+ test('order total includes tax', () => {
32
+ const items = [buildOrderItem({ unitPrice: 100, quantity: 1 })];
33
+ // Real calculateTax runs; test verifies actual behaviour
34
+ expect(getOrderTotal(items)).toBe(105.00);
35
+ });
36
+ ```
37
+
38
+ ---
39
+
40
+ ## MSW (Mock Service Worker) Setup
41
+
42
+ MSW intercepts HTTP requests at the network level. Your application code
43
+ uses real `fetch` / `axios` — no patching required.
44
+
45
+ ### Installation
46
+
47
+ ```bash
48
+ npm install -D msw
49
+ ```
50
+
51
+ ### Handler Definition
52
+
53
+ ```typescript
54
+ // tests/mocks/handlers.ts
55
+ import { http, HttpResponse } from 'msw';
56
+
57
+ export const handlers = [
58
+ http.get('/api/users/:id', ({ params }) => {
59
+ return HttpResponse.json({
60
+ id: params.id,
61
+ name: 'Test User',
62
+ email: 'test@example.com',
63
+ });
64
+ }),
65
+
66
+ http.post('/api/orders', async ({ request }) => {
67
+ const body = await request.json();
68
+ return HttpResponse.json(
69
+ { id: 'order-123', ...body, status: 'created' },
70
+ { status: 201 },
71
+ );
72
+ }),
73
+
74
+ http.get('/api/inventory/:sku', () => {
75
+ return HttpResponse.json({ sku: 'WIDGET-1', stock: 42 });
76
+ }),
77
+ ];
78
+ ```
79
+
80
+ ### Server Setup (Node — Vitest / Jest)
81
+
82
+ ```typescript
83
+ // tests/mocks/server.ts
84
+ import { setupServer } from 'msw/node';
85
+ import { handlers } from './handlers';
86
+
87
+ export const server = setupServer(...handlers);
88
+
89
+ // tests/setup.ts
90
+ import { server } from './mocks/server';
91
+
92
+ beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
93
+ afterEach(() => server.resetHandlers());
94
+ afterAll(() => server.close());
95
+ ```
96
+
97
+ **Critical**: `onUnhandledRequest: 'error'` ensures no real HTTP requests
98
+ leak through. If a test makes an unmocked request, it fails loudly.
99
+
100
+ ### Per-Test Override
101
+
102
+ ```typescript
103
+ import { server } from '../mocks/server';
104
+ import { http, HttpResponse } from 'msw';
105
+
106
+ test('shows error when API returns 500', async () => {
107
+ server.use(
108
+ http.get('/api/users/:id', () => {
109
+ return HttpResponse.json(
110
+ { error: 'Internal server error' },
111
+ { status: 500 },
112
+ );
113
+ }),
114
+ );
115
+
116
+ render(<UserProfile userId="1" />);
117
+ await expect(screen.findByText('Something went wrong')).resolves.toBeInTheDocument();
118
+ });
119
+ ```
120
+
121
+ ### Browser Setup (Playwright / Cypress)
122
+
123
+ For E2E tests, prefer Playwright's built-in route interception over MSW
124
+ browser worker:
125
+
126
+ ```typescript
127
+ // Playwright route mock
128
+ await page.route('**/api/external-service/**', (route) => {
129
+ route.fulfill({
130
+ status: 200,
131
+ contentType: 'application/json',
132
+ body: JSON.stringify({ status: 'ok' }),
133
+ });
134
+ });
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Never Mock What You Don't Own (Without a Contract)
140
+
141
+ If you mock a third-party API, your mock can drift from reality. Protect
142
+ against this:
143
+
144
+ ### Strategy 1: Record and Replay
145
+
146
+ Record real API responses once, replay in tests.
147
+
148
+ ```typescript
149
+ // Record phase (run manually):
150
+ const response = await fetch('https://api.stripe.com/v1/charges');
151
+ fs.writeFileSync('tests/fixtures/stripe-charges.json', await response.text());
152
+
153
+ // Test phase:
154
+ server.use(
155
+ http.get('https://api.stripe.com/v1/charges', () => {
156
+ const data = JSON.parse(fs.readFileSync('tests/fixtures/stripe-charges.json', 'utf-8'));
157
+ return HttpResponse.json(data);
158
+ }),
159
+ );
160
+ ```
161
+
162
+ Refresh recordings periodically (monthly or on API version bump).
163
+
164
+ ### Strategy 2: Schema Validation
165
+
166
+ Validate your mock responses against the provider's OpenAPI spec:
167
+
168
+ ```typescript
169
+ import Ajv from 'ajv';
170
+ import stripeSpec from './fixtures/stripe-openapi.json';
171
+
172
+ test('mock matches Stripe schema', () => {
173
+ const ajv = new Ajv();
174
+ const schema = stripeSpec.paths['/v1/charges'].get.responses['200'].content['application/json'].schema;
175
+ const valid = ajv.validate(schema, mockChargesResponse);
176
+ expect(valid).toBe(true);
177
+ });
178
+ ```
179
+
180
+ ### Strategy 3: Contract Tests
181
+
182
+ For services you own, use Pact (see `test-strategy.md` > Contract Testing).
183
+
184
+ ---
185
+
186
+ ## Verifying Mock Contracts Match Real APIs
187
+
188
+ Every mock handler should be traceable to a real API endpoint. Maintain a
189
+ mapping:
190
+
191
+ ```typescript
192
+ // tests/mocks/contract-map.ts
193
+ /**
194
+ * Maps mock handlers to real API documentation.
195
+ * Review this file when upgrading API versions.
196
+ *
197
+ * Handler: GET /api/users/:id
198
+ * Real endpoint: https://api.example.com/v2/users/{id}
199
+ * Schema: docs/openapi/users.yaml#/paths/~1users~1{id}/get
200
+ * Last verified: 2025-12-01
201
+ */
202
+ ```
203
+
204
+ ### Detecting Drift
205
+
206
+ Add a CI job (weekly) that:
207
+
208
+ 1. Fetches the latest OpenAPI spec from the provider.
209
+ 2. Validates all mock response fixtures against the spec.
210
+ 3. Fails if any fixture is invalid — forces update.
211
+
212
+ ---
213
+
214
+ ## Clock and Random Mocking
215
+
216
+ ### Vitest Clock
217
+
218
+ ```typescript
219
+ import { vi } from 'vitest';
220
+
221
+ test('token expires after 1 hour', () => {
222
+ vi.useFakeTimers();
223
+ vi.setSystemTime(new Date('2025-06-15T10:00:00Z'));
224
+
225
+ const token = createToken();
226
+ expect(token.isExpired()).toBe(false);
227
+
228
+ vi.advanceTimersByTime(60 * 60 * 1000); // 1 hour
229
+ expect(token.isExpired()).toBe(true);
230
+
231
+ vi.useRealTimers();
232
+ });
233
+ ```
234
+
235
+ ### Deterministic Random
236
+
237
+ ```typescript
238
+ test('generates reproducible IDs', () => {
239
+ const mockRandom = vi.spyOn(Math, 'random').mockReturnValue(0.42);
240
+
241
+ const id = generateShortId();
242
+ expect(id).toBe('expected-id-based-on-0.42');
243
+
244
+ mockRandom.mockRestore();
245
+ });
246
+ ```
247
+
248
+ Always restore mocks after the test — use `afterEach(() => vi.restoreAllMocks())`
249
+ globally.