Skip to content

Commit e96a859

Browse files
committed
Streamline documentation - remove verbose content
1 parent 5a4a45c commit e96a859

File tree

10 files changed

+97
-2145
lines changed

10 files changed

+97
-2145
lines changed

docs/architecture/design-decisions.md

Lines changed: 12 additions & 474 deletions
Large diffs are not rendered by default.

docs/architecture/overview.md

Lines changed: 10 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Architecture Overview
22

3-
Pragmatic layered architecture: CLI → Core → Adapters.
4-
53
## Layered Architecture
64

75
```
@@ -22,177 +20,20 @@ Adapters Layer (I/O)
2220

2321
## Dependency Rule
2422

25-
**Unidirectional flow:** CLI → Core → Adapters
23+
Unidirectional flow: CLI → Core → Adapters
2624

2725
- CLI imports Core and Adapters
28-
- Core imports nothing (pure logic)
29-
- Adapters import nothing (isolated I/O)
30-
31-
Benefits: Clean separation, easy testing, framework independence.
32-
33-
## Layer Responsibilities
34-
35-
### CLI Layer
36-
37-
User interaction and terminal UI.
38-
39-
**Responsibilities:**
40-
- Parse arguments (Typer)
41-
- Display output (Rich)
42-
- Orchestrate workflows (calls adapters)
43-
- Bridge sync CLI to async backend
44-
45-
**Files:** `cli/app.py`, `cli/commands/record.py`, `cli/commands/config.py`
46-
47-
### Core Layer
48-
49-
Domain models only.
50-
51-
**Responsibilities:**
52-
- Define TranscriptionStyle enum
53-
54-
**Files:** `core/styles.py`
55-
56-
**Note:** Currently minimal. Orchestration happens in CLI layer (pragmatic choice for small app).
57-
58-
### Adapters Layer
59-
60-
All external I/O.
61-
62-
**Responsibilities:**
63-
- Audio recording (sounddevice)
64-
- WAV file I/O (scipy)
65-
- Whisper API (AsyncOpenAI)
66-
- LLM formatting (PydanticAI)
67-
- Clipboard (pyperclip)
68-
69-
**Files:** `adapters/audio/recorder.py`, `adapters/whisper/client.py`, `adapters/llm/formatter.py`, `adapters/clipboard/manager.py`
26+
- Core imports nothing
27+
- Adapters import nothing
7028

7129
## Data Flow
7230

73-
### Recording Workflow
74-
75-
```
76-
User runs: shh --style casual --translate English
77-
78-
1. CLI Layer (app.py)
79-
├─ Parse args (Typer)
80-
├─ Validate API key exists
81-
└─ Call asyncio.run(record_command(...))
82-
83-
2. CLI Layer (record.py)
84-
├─ Create AudioRecorder
85-
├─ Display progress (Rich Live)
86-
└─ Wait for Enter or max duration
87-
88-
3. Adapters Layer (audio/recorder.py)
89-
└─ Record audio chunks (sounddevice)
90-
91-
4. Adapters Layer (audio/processor.py)
92-
└─ Save to WAV file (scipy)
93-
94-
5. Adapters Layer (whisper/client.py)
95-
└─ Transcribe audio (OpenAI Whisper API)
96-
97-
6. Adapters Layer (llm/formatter.py)
98-
├─ Translate to English (PydanticAI + GPT)
99-
└─ Format with casual style (PydanticAI + GPT)
100-
101-
7. Adapters Layer (clipboard/manager.py)
102-
└─ Copy to clipboard (pyperclip)
103-
104-
8. CLI Layer (record.py)
105-
├─ Display result (Rich Panel)
106-
└─ Clean up temp WAV file
10731
```
108-
109-
### Configuration Workflow
110-
111-
```
112-
User runs: shh config set default_style casual
113-
114-
1. CLI Layer (config.py)
115-
├─ Parse args (key, value)
116-
├─ Validate key exists
117-
└─ Validate value is valid enum
118-
119-
2. Config (settings.py)
120-
├─ Load existing config from JSON
121-
├─ Update setting with validation
122-
└─ Save to platform-specific path
123-
```
124-
125-
## Configuration Architecture
126-
127-
```
128-
┌─────────────────────────────────────────────┐
129-
│ Configuration Priority │
130-
│ 1. CLI Flags (--style casual) │
131-
│ 2. Environment Vars (SHH_DEFAULT_STYLE) │
132-
│ 3. Config File (config.json) │
133-
│ 4. Defaults (hardcoded) │
134-
└─────────────────────────────────────────────┘
135-
136-
137-
┌─────────────────────────────────────────────┐
138-
│ pydantic-settings (Settings class) │
139-
│ • Type validation │
140-
│ • Environment variable parsing │
141-
│ • Default values │
142-
└─────────────────────────────────────────────┘
143-
144-
145-
┌─────────────────────────────────────────────┐
146-
│ Platform-specific Storage │
147-
│ macOS: ~/Library/Application Support/ │
148-
│ Linux: ~/.config/shh/ │
149-
│ Windows: %APPDATA%\shh\ │
150-
└─────────────────────────────────────────────┘
151-
```
152-
153-
## Async Architecture
154-
155-
All I/O operations use async/await for non-blocking execution and responsive UX.
156-
157-
**Key patterns:**
158-
- Async context managers for resource cleanup
159-
- Thread pool executors for blocking I/O (stdin)
160-
- Task cancellation for graceful shutdowns
161-
162-
```python
163-
async with AudioRecorder() as recorder:
164-
await asyncio.sleep(duration)
165-
# Cleanup happens automatically
32+
1. CLI (app.py) - Parse args, validate API key
33+
2. CLI (record.py) - Display progress, wait for Enter
34+
3. Adapters (audio) - Record and save WAV
35+
4. Adapters (whisper) - Transcribe via OpenAI
36+
5. Adapters (llm) - Translate/format via PydanticAI
37+
6. Adapters (clipboard) - Copy result
38+
7. CLI (record.py) - Display result, cleanup
16639
```
167-
168-
## Type Safety
169-
170-
Full `mypy --strict` compliance with type hints on all functions.
171-
172-
**Stack:**
173-
- Pydantic models for structured data
174-
- Enums for finite choices (TranscriptionStyle)
175-
- No `Any` without justification
176-
177-
## Error Handling
178-
179-
Fail fast with clear messages. Adapters translate external errors to domain exceptions. Resources cleaned up in `try/finally` blocks.
180-
181-
```python
182-
try:
183-
result = await transcribe_audio(wav_path, api_key)
184-
finally:
185-
wav_path.unlink(missing_ok=True) # Always clean up
186-
```
187-
188-
## Testing Strategy
189-
190-
Unit tests for core logic, integration tests with mocked APIs. No E2E tests in CI (avoid real API calls).
191-
192-
Target: 80%+ code coverage.
193-
194-
## Next Steps
195-
196-
- [Design Decisions](design-decisions.md)
197-
- [Testing Architecture](testing.md)
198-
- [API Reference](../api-reference/core.md)

0 commit comments

Comments
 (0)