trusty-mpm 1.4.4

trusty-mpm: unified multi-agent orchestration platform (core, daemon, CLI, TUI, Telegram)
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
# Detection Guide: Identifying Testing Anti-Patterns

Comprehensive guide for detecting testing anti-patterns before they cause problems. Includes red flags, warning signs, gate functions, and diagnostic checklists.

## Overview

Prevention is easier than cure. This guide helps you identify anti-patterns during code review, test writing, or debugging test failures.

## Universal Detection Checklist

Run before committing any test:

```
□ Am I asserting on mock elements? (testId='*-mock')
  → If yes: STOP - Test real component or unmock

□ Does this method only exist for tests?
  → If yes: STOP - Move to test utilities

□ Do I fully understand what I'm mocking?
  → If no: STOP - Run with real impl first, then mock minimally

□ Is my mock missing fields the real API has?
  → If yes: STOP - Mirror complete API structure

□ Did I write implementation before test?
  → If yes: STOP - Delete impl, write test first (TDD)

□ Is mock setup >50% of test code?
  → If yes: Consider integration test with real components

□ Can I explain what real behavior this test verifies?
  → If no: STOP - Clarify what you're testing

□ Would this test fail if I removed mocks?
  → If no: You're testing mock behavior
```

## Anti-Pattern 1: Testing Mock Behavior

### Red Flags

**[TypeScript/Jest]**
```typescript
// 🚩 Test ID contains "mock"
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();

// 🚩 Asserting mock was called
expect(mockFunction).toHaveBeenCalled();

// 🚩 Checking mock return values
expect(result).toBe(mockReturnValue);

// 🚩 Test fails when mock removed
// Remove mock → test fails → you're testing mock
```

**[Python/pytest]**
```python
# 🚩 Asserting on mock call behavior
mock_mailer.send_email.assert_called()
mock_mailer.send_email.assert_called_once()
mock_mailer.send_email.assert_called_with("user@example.com", "Welcome!")

# 🚩 Checking mock attributes
assert mock_mailer.send_email.called
assert mock_mailer.send_email.call_count == 1

# 🚩 Test fails when mock removed
# Remove mock → test fails → you're testing mock
```

**Language patterns:**
- "Make sure the mock..."
- "Test that component renders mock"
- "Verify mock is present"
- "Check if mock function called"

**Diagnostic questions:**
1. **"If I remove this mock, does test still make sense?"**
   - No → You're testing mock behavior
   - Yes → Good, test tests real behavior

2. **"What production behavior does this verify?"**
   - Can't answer → Testing mock behavior
   - Clear answer → Good

3. **"Would this test catch real bugs?"**
   - No → Testing mock behavior
   - Yes → Good

### Detection Script

```typescript
// Run this check on your tests
function detectsMockTesting(testFile: string): string[] {
  const warnings: string[] = [];

  // Pattern: testId with 'mock'
  if (testFile.includes("getByTestId('") && testFile.includes('-mock')) {
    warnings.push('Testing mock element by test ID');
  }

  // Pattern: expecting on mock objects
  if (testFile.includes('expect(mock') && testFile.includes('toBe')) {
    warnings.push('Asserting on mock values');
  }

  // Pattern: mock call assertions without behavior check
  if (testFile.includes('toHaveBeenCalled') &&
      !testFile.includes('expect(result)')) {
    warnings.push('Only checking mock calls, not results');
  }

  return warnings;
}
```

## Anti-Pattern 2: Test-Only Methods in Production

### Red Flags

**[TypeScript/Jest]**
```typescript
// 🚩 Method only called in test files
// Search: "destroy(" → Only in *.test.ts files

// 🚩 Method names suggesting test use
class Session {
  reset()    // 🚩
  destroy()  // 🚩
  clear()    // 🚩
  mock()     // 🚩
}

// 🚩 Comments acknowledging test-only use
// "For testing only"
// "Used by test cleanup"
```

**[Python/pytest]**
```python
# 🚩 Methods only called in test files
# Search: "_set_mock" → Only in test_*.py files

# 🚩 Method names suggesting test use
class UserService:
    def _set_mock_db(self, db):  # 🚩
        pass
    def _reset_for_testing(self):  # 🚩
        pass
    def _mock_dependencies(self):  # 🚩
        pass

# 🚩 Docstrings acknowledging test-only use
"""For testing only"""
"""Used by test fixtures"""
```

**File analysis:**

**[TypeScript/Jest]**
```bash
# Find methods only called in tests
grep -r "\.destroy\(" --include="*.ts" | grep -v ".test.ts"
# If empty → method only in tests → move to test utils
```

**[Python/pytest]**
```bash
# Find methods only called in tests
grep -r "\._set_mock" --include="*.py" | grep -v "test_"
# If empty → method only in tests → move to test utils
```

**Diagnostic questions:**
1. **"Is this method called outside test files?"**
   - No → Test-only method, move to utilities
   - Yes → Keep in production

2. **"Would production code ever need this?"**
   - No → Move to test utilities
   - Yes → Keep in production

3. **"Does this class own this resource's lifecycle?"**
   - No → Wrong place for this method
   - Yes → Consider if needed in production

### Detection Script

```typescript
// Analyze method usage
function findTestOnlyMethods(codebase: string[]): Report {
  const methods = extractMethods(codebase);

  return methods.filter(method => {
    const usages = findUsages(method);
    const testUsages = usages.filter(u => u.file.includes('.test.'));
    const prodUsages = usages.filter(u => !u.file.includes('.test.'));

    return testUsages.length > 0 && prodUsages.length === 0;
  });
}
```

## Anti-Pattern 3: Mocking Without Understanding

### Red Flags

**Code indicators:**
```typescript
// 🚩 Mocking without reading implementation
vi.mock('SomeModule');  // What does it do? Unknown.

// 🚩 "Just to be safe" mocking
// Mock everything, understand nothing

// 🚩 Test mysteriously fails/passes
// You can't explain why

// 🚩 Mock prevents test logic from working
vi.mock('UserService');  // Breaks user creation test needs
```

**Language patterns:**
- "I'll mock this to be safe"
- "This might be slow"
- "Let's mock everything"
- "Not sure why test fails"

**Diagnostic questions:**
1. **"What side effects does the real method have?"**
   - Can't answer → Don't mock yet
   - Know all effects → Can mock safely

2. **"Does my test depend on any of those side effects?"**
   - Yes → Don't mock at this level
   - No → Safe to mock

3. **"Where is the actual slow/external operation?"**
   - Unclear → Study code first
   - Clear → Mock at that level

### Detection Strategy

**Before mocking:**
```
1. Read the implementation
   - What does it do?
   - What are side effects?
   - What does it return?

2. Run test with real implementation
   - How slow is it? (measure!)
   - What behavior occurs?
   - What's actually needed?

3. Identify minimal mock point
   - Where is the slow/external operation?
   - Can I mock below this level?
   - What behavior must be preserved?

4. Mock at correct level
   - Mock boundary of slow operation
   - Preserve logic test depends on
   - Verify test still tests intended behavior
```

### Speed Measurement

```typescript
// Measure before mocking
test('user registration', async () => {
  const start = performance.now();
  await registerUser(userData);
  const duration = performance.now() - start;

  console.log(`Test took ${duration}ms`);
  // If <100ms → Don't mock
  // If >1000ms → Identify slow part
});
```

## Anti-Pattern 4: Incomplete Mocks

### Red Flags

**Code indicators:**
```typescript
// 🚩 Mock created from memory
const mock = { id: '123' };  // What other fields exist?

// 🚩 Partial type annotation
const mock: Partial<User> = { id: '123' };

// 🚩 Different tests, different mock shapes
// test1.ts: { id, name }
// test2.ts: { id, name, email, profile }

// 🚩 Comment acknowledging incompleteness
// "TODO: add more fields"
// "Add fields as needed"
```

**Missing documentation:**
- No reference to API docs
- No TypeScript interface
- No factory function
- Copy-pasted mock variations

**Diagnostic questions:**
1. **"What does the real API return?"**
   - Can't answer → Check docs before mocking
   - Know structure → Use it in mock

2. **"Am I using TypeScript types?"**
   - No → Add types to enforce completeness
   - Yes → Good

3. **"Do other tests mock this differently?"**
   - Yes → Inconsistent mocks, need factory
   - No → Good

### Detection Script

```typescript
// Find incomplete mocks
function detectIncompleteMocks(testFile: string): Warning[] {
  const warnings: Warning[] = [];

  // Pattern: Partial<T> in test
  if (testFile.includes('Partial<') && testFile.includes('mock')) {
    warnings.push('Using Partial type for mock - likely incomplete');
  }

  // Pattern: Object literals without types
  const mockPattern = /const mock\w+ = \{[^}]+\};/g;
  const mocks = testFile.match(mockPattern);

  if (mocks) {
    mocks.forEach(mock => {
      if (!mock.includes(': ')) {  // No type annotation
        warnings.push('Mock without type annotation');
      }
    });
  }

  return warnings;
}
```

### Completeness Checklist

```
□ Referenced API documentation
□ Used TypeScript interface/type
□ Included all required fields
□ Included optional fields (as null/undefined)
□ Nested objects complete
□ Arrays have realistic length/content
□ Metadata fields included
□ Timestamps/IDs present
```

## Anti-Pattern 5: Tests as Afterthought

### Red Flags

**Process indicators:**
```
🚩 PR has implementation commits, then "add tests" commit
🚩 "Ready for testing" status on untested feature
🚩 Test coverage added after code review
🚩 Tests written to pass, not fail first
🚩 Implementation complete, tests pending
```

**Language patterns:**
- "I'll add tests next"
- "Implementation done, needs tests"
- "Ready for testing phase"
- "Tests coming soon"

**Code indicators:**
```typescript
// 🚩 Tests that can't fail
test('feature works', () => {
  const result = newFeature();
  expect(result).toBe(result);  // Always passes
});

// 🚩 Tests with no assertions
test('feature runs', () => {
  newFeature();  // No expect()
});
```

**Diagnostic questions:**
1. **"Did I write test before implementation?"**
   - No → Not following TDD
   - Yes → Good

2. **"Did I watch test fail first?"**
   - No → Can't verify test works
   - Yes → Good

3. **"Are there commits without tests?"**
   - Yes → Tests afterthought
   - No → Good

### Git History Analysis

```bash
# Check if tests come after implementation
git log --oneline --name-only | grep -A5 "feature"

# Red flag pattern:
# abc123 Add feature X
#   src/feature.ts
# def456 Add tests for feature X  ← Tests after
#   src/feature.test.ts

# Good pattern:
# abc123 Add feature X with tests
#   src/feature.test.ts  ← Test file in same commit
#   src/feature.ts
```

## Warning Signs: When Mocks Become Too Complex

### Complexity Indicators

```typescript
// 🚩 Mock setup longer than test
const setup = 50 lines;
const test = 10 lines;
// Ratio > 3:1 → Too complex

// 🚩 Mocking everything
vi.mock('ModuleA');
vi.mock('ModuleB');
vi.mock('ModuleC');
vi.mock('ModuleD');
// 4+ mocks → Consider integration test

// 🚩 Nested mock setup
const mockA = { mock: mockB };
const mockB = { mock: mockC };
const mockC = { /* ... */ };

// 🚩 Mock setup in beforeEach for single test
beforeEach(() => {
  // 30 lines of setup
});

test('one thing', () => {
  // 5 lines
});
```

**Your human partner's question:** "Do we need to be using a mock here?"

**Consider:** Integration tests with real components often simpler than complex mocks.

### Complexity Metrics

```typescript
function calculateMockComplexity(test: TestFile): ComplexityScore {
  return {
    mockCount: countMocks(test),           // >4 is high
    setupLines: countSetupLines(test),     // >30 is high
    setupToTestRatio: setupLines / testLines,  // >3 is high
    mockNestingDepth: calculateNesting(test),  // >2 is high

    recommendation: score > 10 ? 'Use integration test' : 'OK'
  };
}
```

## Comprehensive Code Review Checklist

Use this when reviewing tests (yours or others'):

### Structure
```
□ Test files exist for new code
□ Tests in same commit as implementation
□ Tests follow TDD pattern (fail first)
□ Clear test names describe behavior
```

### Mock Usage
```
□ Mocks used sparingly (only when needed)
□ Mock setup is simple (<20 lines)
□ Mocks at correct level (I/O boundaries)
□ No assertions on mock elements
□ Complete mock structures (all fields)
```

### Production Code
```
□ No test-only methods in production classes
□ No test-specific logic in production
□ Clean separation of concerns
□ No test imports in production code
```

### Test Quality
```
□ Tests verify real behavior
□ Assertions on meaningful results
□ Edge cases covered
□ Error conditions tested
□ Integration tests for critical paths
```

### Red Flags
```
□ No 'testId="*-mock"' assertions
□ No Partial<T> for mocks
□ No "for testing" comments in production
□ No untested implementation commits
```

## Automated Detection Tools

### ESLint Rules

```javascript
// .eslintrc.js
module.exports = {
  rules: {
    // Prevent test-only methods
    'no-restricted-syntax': [
      'error',
      {
        selector: 'MethodDefinition[key.name=/^(reset|destroy|clear|mock)$/]',
        message: 'Potential test-only method in production code'
      }
    ],

    // Prevent mock test IDs
    'testing-library/prefer-screen-queries': 'error',
    'testing-library/no-node-access': 'error',
  }
};
```

### Pre-commit Hook

```bash
#!/bin/bash
# .git/hooks/pre-commit

# Check for mock test IDs
if git diff --cached | grep -q "testId=.*-mock"; then
  echo "Error: Found mock test ID in tests"
  echo "Are you testing mock behavior?"
  exit 1
fi

# Check for test-only methods
if git diff --cached -- "*.ts" "*.js" | \
   grep -v ".test." | \
   grep -q "destroy()\|reset()\|clear()"; then
  echo "Warning: Potential test-only method in production code"
fi

# Check test coverage
npm test -- --coverage --coverageThreshold='{"global":{"lines":80}}'
```

## Quick Reference: Detection Summary

| Anti-Pattern | Key Indicator | Quick Check |
|--------------|---------------|-------------|
| Testing Mock Behavior | testId='*-mock' | Remove mock - test still valid? |
| Test-Only Methods | Method only in .test. files | grep production files |
| Mocking Without Understanding | Can't explain why mocking | Read implementation first |
| Incomplete Mocks | Partial<T> or no types | Check against API docs |
| Tests as Afterthought | Implementation before tests | Check git history |

## Python/pytest-Specific Detection Patterns

### Red Flags Unique to Python

**Over-reliance on unittest.mock:**
```python
# 🚩 Using Mock() for data objects
mock_user = Mock()
mock_user.id = 123
mock_user.name = "Alice"
# Should use dataclass or fixture factory instead

# 🚩 MagicMock without spec
mock_service = MagicMock()
# Should specify spec=RealService to catch attribute errors

# 🚩 Global @patch decorators
@patch('module.function1')
@patch('module.function2')
@patch('module.function3')
def test_something(...):
    # Too broad - over-mocking
```

**Fixture Abuse:**
```python
# 🚩 autouse fixtures without clear need
@pytest.fixture(autouse=True)
def setup_everything():
    # Hidden dependency - tests unclear

# 🚩 Fixture bloat
@pytest.fixture
def user(db, session, config, mailer, cache, queue):
    # Too many dependencies

# 🚩 Complex fixture chains
@pytest.fixture
def user(profile, settings, permissions):
    # Each has more fixtures - hard to understand
```

**pytest-mock Patterns:**
```python
# 🚩 Mocking at wrong level
mocker.patch('user_service.UserRepository')  # Too high
# Should mock database connection, not repository

# 🚩 Missing spec parameter
mocker.patch('requests.post')  # No spec
# Should use spec=requests.post or spec_set

# 🚩 Asserting on mock calls without behavior check
mock_mailer.send_email.assert_called_once()
# But no assertion on actual result!
```

### Python Detection Script

```python
# Check for anti-patterns in Python tests
def detect_python_anti_patterns(test_file: str) -> list[str]:
    warnings = []

    # Pattern: Mock assertions without behavior checks
    if '.assert_called' in test_file and 'assert ' not in test_file:
        warnings.append('Mock assertions without real behavior checks')

    # Pattern: Using Mock() for data objects
    if 'Mock()' in test_file and 'dataclass' not in test_file:
        warnings.append('Using Mock() for data - use dataclass/fixture')

    # Pattern: @patch without spec
    if '@patch(' in test_file and 'spec=' not in test_file:
        warnings.append('@patch without spec parameter')

    # Pattern: Too many autouse fixtures
    autouse_count = test_file.count('autouse=True')
    if autouse_count > 2:
        warnings.append(f'{autouse_count} autouse fixtures - hidden dependencies')

    return warnings
```

### pytest Best Practices Checklist

```
□ Use fixtures instead of mocks when possible
□ Specify spec= on @patch decorators
□ Use dataclasses/factories for test data, not Mock()
□ Limit autouse fixtures to truly global setup
□ Prefer monkeypatch over @patch for simple cases
□ Use parametrize instead of loops
□ Keep fixture chains shallow (<3 levels)
□ Mock at I/O boundaries (requests, database), not business logic
```

## When to Seek Help

**STOP and ask your human partner if:**
- Mock setup exceeds 50 lines
- You've mocked >5 modules in one test
- Test mysteriously passes/fails
- You can't explain what test verifies
- Same test needs different mocks in different runs
- Integration test seems simpler than mocks
- Fixture chain depth >3 levels (Python/pytest)
- Using Mock() for data objects (Python)

**Questions to ask:**
- "Do we need to be using a mock here?"
- "Should this be an integration test?"
- "Am I testing the right thing?"
- "Is this test-only method necessary?"
- "Should this be a fixture instead of a mock?" (Python/pytest)
- "Can I use a fake/test double instead?" (Python/pytest)

## Prevention Mindset

**Before writing any test:**
1. Understand what you're testing (real behavior)
2. Write test first (TDD)
3. Watch it fail
4. Minimal implementation
5. Watch it pass
6. Refactor

**This workflow prevents all five anti-patterns naturally.**

See the Test-Driven Development skill for complete TDD workflow (available in the skill library for comprehensive TDD guidance).