Before Making Changes
- Understand the current state by reading relevant test files.
- Check
cosmo/core/config/settings.yamlfor configuration that affects behavior. - Verify changes against the actual source code, not documentation.
- Run focused tests before hardware-dependent tests.
When Adding Features
- Define event names in
cosmo/core/events/event_types.pyif event-driven. - Add listener registration in
cosmo/core/bootstrap/bootstrap.py. - Emit events from implementation code with correct priority.
- Add tests that match the real emitted lifecycle.
- Update configuration in
settings.yamlif adding configurable behavior.
Documentation Rules
- Documentation must reflect actual code state, not intended design.
- If a module is experimental, mark it as experimental.
- Keep diagrams updated after architectural changes.
- When adding a new subsystem, update overview, architecture, configuration, testing, troubleshooting, known limitations, and roadmap.
- Do not describe roadmap items as implemented features.
When Modifying Audio/Wakeword
- Verify Vosk model directory exists:
cosmo/models/vosk/vosk-model-small-pt-0.3/. - Check sample rate, chunk size, and silence thresholds are consistent.
- Test with actual microphone and audio files.
- Monitor CPU usage; adjust
energy_thresholdandidle_sleepif needed. - Run
test_tts_pipeline.pyto validate end-to-end audio flow.
When Modifying Personality
- Test parser behavior with
test_persona_command_parser.py. - Verify JSON persistence with
test_persona_persistance.py. - Test prompt construction with
test_persona_command_integration.py. - Check that parameter values clamp to 0-100.
- Validate database aliases are loaded correctly.
When Modifying Memory
- Validate extraction rules do not fire on normal conversation.
- Run filter tests:
test_memory_filter.py. - Test duplicate prevention:
test_memory_manager.py. - Verify SQLite storage and retrieval:
test_database.py. - Check memory context injection in prompts.
When Adding Local Commands
- Add to the
local_commandstable in SQLite. - Test phrase matching with normalization:
test_local_command_db.py. - Keep handler logic deterministic and quick.
- Avoid LLM calls; use fallback responses for errors.
- Save conversation through
MemoryManager.process_interaction()for audit.
High-Signal Validation by Subsystem
| Subsystem | Tests | Validation |
|---|---|---|
| Database | test_database.py | All repositories create/read/update/delete. |
| Memory | test_memory_filter.py, test_memory_manager.py, test_response_generator_memory_integration.py | Extraction, filtering, deduplication, injection. |
| Local commands | test_local_command_db.py, test_local_status_command.py, test_local_memory_commands.py | Phrase matching, execution, conversation saving. |
| Personality | test_persona_command_parser.py, test_persona_command_integration.py, test_persona_persistance.py | Parsing, state update, persistence. |
| Runtime/event bus | test_runtime_state.py, test_concurrency_guards.py, priority_test.py, critical_event_test.py | State transitions, guards, event ordering, resilience. |
| Diagnostics | test_diagnostics_manager.py | Snapshot structure and metrics. |
Common Patterns to Follow
- Import singletons:
from cosmo.core.config.settings_manager import config. - Emit events with priority:
await async_event_bus.emit(name, data, priority=PRIORITY_AUDIO). - Check guards before state changes:
if not runtime_state.can_start_thinking(): return. - Use repository pattern for data access:
memory_repository.add_memory(...). - Create background tasks for non-blocking work:
asyncio.create_task(long_running_coro()). - Log lifecycle events:
logger.info(f"Starting component...").
Code Quality Standards
- Use type hints where practical.
- Follow existing naming conventions: snake_case for functions and variables.
- Keep methods focused on single responsibility.
- Test error paths, not just happy paths.
- Document non-obvious behavior in docstrings or comments.
- Avoid global state except singletons: logger, config, db, event bus, runtime_state.

