Document Version: 1.0 Date: 2026-04-08 Status: ACTIVE - Defines quality requirements for engine-sim-cli project Purpose: Clear requirements for code quality, testing, and development practices
This document defines the quality standards that all team members must follow. It establishes clear expectations, protocols for handling test failures, consequences for violations, and provides training materials for the quality safeguards.
- Test-Driven Development (TDD): Write tests BEFORE implementing features
- Red-Green-Refactor Cycle: Tests must compile before implementation (RED phase)
- Evidence-Based Decision Making: Gather evidence, don't speculate unless asked
- Critical Thinking: Challenge assumptions, verify facts before proceeding
- SOLID Principles: Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, Dependency Inversion
- Test Value: Tests must add real business value, not just coverage vanity
- Determinism: Tests must be deterministic and repeatable
| Principle | Definition | Requirements |
|---|---|---|
| SRP | Single Responsibility Principle | Each class/function has one reason to change |
| OCP | Open-Closed Principle | Open for extension, closed for modification |
| LSP | Liskov Substitution Principle | Subtypes must be substitutable for base types |
| ISP | Interface Segregation Principle | Focused, minimal interfaces |
| DIP | Dependency Inversion Principle | Depend on abstractions, not concretions |
| Requirement | Definition | Acceptance Criteria |
|---|---|---|
| TDD Compliance | Tests written before implementation | - Test file created before feature file - Test compiles in RED phase - Implementation makes tests GREEN |
| Real Business Value | Tests validate production scenarios | - Tests use real production code paths - Tests use mocks to control scenarios - Tests don't test truisms - Tests don't test themselves |
| Determinism | Tests produce consistent results | - Same inputs produce same outputs - Tests pass in any order - No hidden state between test runs |
| Exception Testing | Test error conditions appropriately | - Test intent, not exact error messages - Test exception types and key information - Avoid fragile string comparisons |
| Test Independence | Tests don't depend on each other | - Each test can run in isolation - No test execution order dependencies - Tests don't create shared state |
| Requirement | Definition | Acceptance Criteria |
|---|---|---|
| File Organization | Clear module structure | - Logical folder hierarchy - One class per file where practical - Related files grouped in same directory |
| Naming Conventions | Consistent naming patterns | - Classes use PascalCase - Functions use camelCase - Constants use UPPER_CASE - Files use PascalCase - Interfaces start with I |
| Documentation | Code is self-documenting | - Public interfaces have clear documentation - Complex logic has comments - No TODO comments without issue reference |
| DRY Compliance | Don't Repeat Yourself | - No duplicate code >5 lines - Extract common functionality to utilities - Use existing functions instead of rewriting |
| YAGNI Compliance | You Aren't Gonna Need It | - No unused code that was never used - No features added "just in case" - No over-engineering for hypothetical future needs |
When a test fails, follow this protocol:
- STOP: Immediately stop current work
- ANALYZE: Read test failure message carefully
- REPRODUCE: Attempt to reproduce the failure locally
- ROOT CAUSE: Identify the root cause, not just surface symptoms
- FIX: Implement minimal fix that addresses root cause
- VERIFY: Run the specific failing test to verify the fix
- REGRESSION: Run related tests to ensure no regressions
- DOCUMENT: Document the fix with explanation
A "critical" test failure is one that:
- Blocks team members from continuing work
- Prevents builds from succeeding
- Causes production functionality to break
- Indicates architectural or design problem
Protocol for Critical Failures:
- Immediate Notification to team-lead and product-owner
- Stop All Related Work until failure is resolved
- Assign Priority - Critical failures are P0, must be addressed immediately
- Timebox Investigation - Maximum 4 hours for initial root cause analysis
- Require Approval - Critical fixes require team approval before committing
When tests produce different results on repeated runs, this indicates loss of determinism.
Protocol:
- Verify Test Setup - Check for hidden state, timing dependencies
- Isolate Component - Test components in isolation
- Check Float Precision - Floating point calculations can cause small variations
- Review State Management - Ensure complete cleanup between test runs
- Add Logging - Add diagnostic logging to understand behavior differences
Integration test failures indicate problems with component interaction.
Protocol:
- Check Component Initialization - Verify all components properly initialized
- Check Data Flow - Verify data flows correctly between components
- Check Configuration - Verify test configuration is correct
- Check Environment - Verify test environment is properly set up
- Verify Mock Behavior - Ensure mocks behave as expected
| Severity | Definition | Consequences |
|---|---|---|
| CRITICAL | Violates quality standards, breaks critical functionality | - Immediate fix required - Blocks team work - Requires team approval - May result in code rollback |
| HIGH | Violates quality standards, affects important functionality | - Fix within current sprint - Blocks dependent work - Requires notification to team |
| MEDIUM | Violates quality standards, affects non-critical areas | - Fix within 2 sprints - Document in backlog - May result in tech debt ticket |
| LOW | Minor violation, doesn't affect functionality | - Fix when convenient - Document for future cleanup - Technical debt item created |
Definition: Committing code without running the full test suite.
Consequences: CRITICAL
- Immediate rollback of violating commit required
- All subsequent work blocked until tests are green
- Team meeting required to discuss violation
Example: "Skipping failing test X to unblock work Y" is a violation.
Definition: Writing tests that don't compile or that test non-existent behavior.
Consequences: CRITICAL
- Test must be rewritten or removed
- Cannot commit feature until test is fixed
- Team code review required
Example: "Test for null pointer crash" that dereferences null is invalid.
Definition: Code produces different results for same inputs, making debugging difficult.
Consequences: HIGH
- Must be addressed before feature is considered complete
- Requires investigation and root cause fix
- May require refactoring
Example: Using time-based random number generation without seeding.
Definition: Deliberately choosing not to follow quality standards despite awareness.
Consequences: CRITICAL
- Immediate team intervention required
- Code review cannot approve work
- Possible disciplinary action
Example: "Skipping TDD because it takes too long" is a violation.
Definition: Tests that break easily due to implementation details not intended behavior.
Consequences: MEDIUM
- Tests must be refactored to test intent, not implementation
- Test coverage should not be primary metric
- Tests must add real business value
Example: Tests that check exact error message strings instead of exception types.
Location: verification_system.sh
Purpose: Comprehensive verification of all fixes and functionality.
How to Use:
# Run full verification
./verification_system.sh
# Run specific verification mode
./verification_system.sh --mode audio
./verification_system.sh --mode input
./verification_system.sh --mode engineWhat It Tests:
- Audio output with frequency measurement
- Input response timing
- Engine startup behavior
- Binary verification
- Configuration validation
Interpreting Results:
- All PASSING: Fix is verified working
- PARTIAL PASSING: Fix works but has edge cases
- FAILING: Fix does not work, root cause analysis needed
Document: TESTING_GUIDE.md
Purpose: Guidelines for writing effective tests.
Key Principles:
- Test Real Production Code: Don't test mocks or external libraries
- Test Business Scenarios: Test actual usage patterns, not edge cases
- Test Intent, Not Implementation: Test what should happen, not how it happens
- Use Mocks to Control Scenarios: Mocks enable testing specific conditions
- Avoid Fragile Tests: Don't depend on exact error messages or implementation details
- Prioritize Happy Path: Test main success scenarios first, reasonable exception cases second
Test Value Criteria:
- Does this test catch real bugs?
- Does this test prevent regressions?
- Does this test verify important user requirements?
- Would this test's failure block production release?
| Principle | Practical Guidelines |
|---|---|
| SRP | - Ask: "What is the single responsibility of this class?" - Limit: Classes should have 1-3 major responsibilities - Avoid: God objects, Swiss army knives |
| OCP | - Ask: "Can I add new behavior without modifying this class?" - Use: Strategy pattern, Factory pattern - Avoid: Hard-coded type checks, conditional logic for object creation |
| LSP | - Ask: "Can I substitute this subtype without breaking behavior?" - Ensure: Base class contracts honored by all implementations |
| ISP | - Ask: "Do clients need all methods in this interface?" - Design: Small, focused interfaces - Avoid: Fat interfaces, method grouping for convenience |
| DIP | - Ask: "Does this depend on concrete implementation?" - Design: Depend on abstractions - Use: Dependency injection, constructor injection |
| Violation | How to Avoid | Example |
|---|---|---|
| SRP: Too Many Responsibilities | Extract classes using extract method refactoring | Class with audio, logging, configuration, UI - split into AudioPlayer, Logger, ConfigManager |
| OCP: Conditional Type Logic | Use polymorphism instead of if/else chains | if (type == "threaded") vs StrategyFactory::create(AudioMode::Threaded) |
| ISP: Fat Interfaces | Split into smaller, focused interfaces | IAudioProcessor with 15 methods -> IAudioGenerator, IAudioProcessor, IMixer |
| DIP: Direct Instantiation | Use factory or DI instead of new | new AudioPlayer() vs audioPlayer = factory.create() |
| DRY: Duplicate Code | Extract to shared utility function | Same validation logic in 3 places -> one utility function |
The project enforces quality checks before commits:
Checks Performed:
- Test Suite Status: All tests must be passing
- Code Review: At least one team member approval required
- SOLID Compliance: Code review must verify SOLID principles
- Documentation: New features must be documented
- TDD Compliance: Tests must exist for new features
When Checks Fail:
- Commit is blocked
- Root cause analysis required
- Team meeting may be required
Continuous Integration Requirements:
- All Tests Must Pass: Build fails if any test fails
- No Code Compilation Warnings: Treat warnings as errors
- Code Coverage Minimum: Maintain 80%+ coverage for new code
- Static Analysis: No violations from linters/static analyzers
- Documentation Build: Documentation must build without errors
Purpose: Automatically verify quality standards before commits.
How It Works:
- Test Check: Runs full test suite
- Code Quality Check: Runs static analysis and linting
- Documentation Check: Validates documentation completeness
- Commit Blocking: Blocks commit if any check fails
File: .git/hooks/pre-commit
Required Checks:
# Run all tests
make test
# Check exit code
if [ $? -ne 0 ]; then
echo "ERROR: Tests are failing. Cannot commit."
exit 1
fi
# Run static analysis
make static-analysis
# Check for SOLID violations
make solid-checkPurpose: Track all test failures and their resolutions.
Components:
- Failure Database: Records each test failure with details
- Root Cause Analysis: Documents investigation and resolution
- Prevention: Documents preventive measures
File: test/TEST_FAILURE_LOG.md
Example Entry:
## Failure #42: Deterministic Test Failure
**Date**: 2026-04-08
**Test**: SineWave_SyncPull_DeterministicRepeatability
**Severity**: CRITICAL
**Symptoms**:
- 76% difference between runs
- Loss of determinism
- Inconsistent output for same inputs
**Root Cause**:
- State accumulation between test runs
- Floating point precision issues
- Incomplete cleanup of simulator state
**Resolution**:
- Added explicit cleanup in test teardown
- Fixed floating point precision issues
- Added diagnostic logging
**Prevention**:
- All tests now include explicit cleanup
- State management utility created for test isolation
- Floating point usage guidelines added
**Verification**:
- Test now passes with <5% variance
- Verified with 10 consecutive runsCurrent Components:
Audio Module
├── IAudioStrategy (Interface)
│ ├── ThreadedStrategy (Implementation)
│ └── SyncPullStrategy (Implementation)
├── IAudioHardwareProvider (Interface)
│ └── CoreAudioHardwareProvider (Implementation)
├── State Management
│ ├── AudioState
│ ├── BufferState
│ ├── Diagnostics
│ └── StrategyContext (Composer)
└── Common Utilities
├── CircularBuffer
└── AudioUtils
Quality Safeguards:
- All interfaces are minimal and focused
- Each component has single responsibility
- Dependencies are inverted (depend on abstractions)
- Strategy pattern enables swappable behaviors
- Factory pattern for object creation
Components:
Verification System
├── verification_system.sh (Main Script)
├── Audio Verification
│ ├── Frequency measurement
│ ├── Amplitude analysis
│ └── Output validation
├── Input Verification
│ ├── Keypress timing
│ └── Control response
├── Engine Verification
│ ├── Startup monitoring
│ ├── RPM tracking
│ └── Hang detection
└── Binary Verification
├── Dependency checking
└── Integrity validation
Quality Safeguards:
- Each verification script is independent
- Clear pass/fail criteria
- Diagnostic output for debugging
- Automated for consistency
When Tests Fail:
- Immediate Communication: Notify team in appropriate channel
- Stop Work: Halt related work until failure is understood
- Root Cause Analysis: Don't just fix symptoms
- Timebox: 4 hours maximum for initial investigation
- Ask for Help: If stuck, escalate immediately
When Standards Violated:
- Identify Violation: Reference this document for definition
- Determine Severity: Use severity levels from Section 3.1
- Follow Consequences: Apply consequences from Section 3.2
- Learn: Document lessons learned for prevention
During Code Review:
- Quality Checklist: Use checklist from this document
- Test Coverage Review: Verify tests add real value
- SOLID Review: Verify each principle for compliance
- Documentation Review: Ensure code is self-documenting
- Ask Questions: Challenge assumptions, verify decisions
VERIFICATION_README.md- Comprehensive verification system documentationTESTING_GUIDE.md- Testing best practices and guidelinesARCHITECTURE_TODO.md- Architecture task trackingARCHITECTURE_AUDIT.md- Architecture audit findingsAUDIO_MODULE_ARCHITECTURE.md- Audio module architecture documentation
Historical investigation and audit documents are archived in docs/archive/:
ARCHITECTURE_COMPARISON_REPORT.md- Architecture comparison analysisACTION_PLAN.md- Original action planANALYSIS_CORRECTIONS.md- Analysis correctionsAUDIO_PIPELINE_VERIFICATION.md- Audio pipeline verification
The quality system consists of:
- Pre-commit hooks for test and quality enforcement
- CI pipeline requirements for automated checks
- Test failure tracking and prevention
- Comprehensive standards documentation (this document)
- Training materials for team onboarding
| Term | Definition |
|---|---|
| TDD | Test-Driven Development - writing tests before implementation |
| SOLID | Single Responsibility, Open-Closed, Liskov, Interface Segregation, Dependency Inversion |
| DRY | Don't Repeat Yourself - avoiding duplicate code |
| YAGNI | You Aren't Gonna Need It - avoiding over-engineering |
| Determinism | Property of producing same output for same input consistently |
| SRP Violation | Class has more than 3 major responsibilities |
| God Object | Class that does too many things |
| Fat Interface | Interface with too many methods (>5) |
| Technical Debt | Implementation shortcuts that need future refactoring |
| Regression | Bug introduced that breaks previously working functionality |
Document End