Two files, one repository
SethRobinson/UGTLive ships 2 formats across 13 indexed files. The question worth asking is whether the second one says anything the first does not.
CompareAGENTS.md ↔ Cursor rules
| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 7 | 49 | 0% |
| Commands | 0 | 3 | 0 | 0% |
| Section tags | 2 | 3 | 8 | 15% |
What each file covers
Sections
0 shared · 7 only in A · 49 only in B- − AGENTS.md
- − Shared Project Memory
- − Testing
- − Cloud LLM Model Maintenance
- − Feature Index
- − Security
- − Git
- + Architecture Patterns
- + Project Structure
- + Directory Organization
- + File Naming
- + Design Patterns
- + Singleton Pattern
- + Factory Pattern
- + Strategy Pattern
- + Separation of Concerns
- + UI Layer
- + Business Logic Layer
- + Data Layer
- + Dependency Management
- + Service Dependencies
- + Manager Dependencies
- + Communication Patterns
- + Window Communication
- + Event-Driven Architecture
- + Hotkey System
- + Resource Management
- + Disposable Resources
- + Using Statements
- + State Management
- + Application State
- + Runtime State
- + Error Propagation
- + Error Handling Strategy
- + Extension Points
- + Adding New Translation Service
- + Adding New OCR Method
- + Adding New Python OCR Service
- + Performance Considerations
- + Lazy Initialization
- + Caching
- + Threading Model
- + UI Thread
- + Background Threads
- + Module Boundaries
- + Service Boundaries
- + Manager Boundaries
- + Testing Architecture
- + Testable Components
- + Mock-Friendly Design
- + Version Management
- + Version Updates
- + Version Format
- + Build Configuration
- + Output Structure
- + Dependencies
Commands
0 shared · 3 only in A · 0 only in B- − dotnet build .\UGTLive.sln --configuration Release
- − git commit
- − git push
Section tags
2 shared · 3 only in A · 8 only in B- − git-pr
- − security
- − do-not
- + build
- + lint-format
- + code-style
- + architecture
- + testing-strategy
- + dependencies
- + ui
- + deployment
- test
- performance
Line diff
SethRobinson/UGTLive · AGENTS.md
@@ −1 @@
1# AGENTS.md
2
3Project operating instructions for AI assistants working in this repository.
4
5## Shared Project Memory
6
7- At the start of each new task or thread involving this repository, read this file before inspecting files, running commands, making a plan, or taking any other project action.
8- Treat follow-up replies in the same continuous task as part of that task. Do not reread this file unless the repository or working directory changes, this file is modified, or its instructions are no longer available in context.
9- Treat this file as the shared project memory for AI assistants.
10- Do not rely on vendor-specific, proprietary, or hidden memory systems for project facts, preferences, or operating instructions. (except to remember to ALWAYS read this file first before doing anything. Remember that.)
11- Update this file with important repo-specific information learned during work, including build commands, test commands, conventions, decisions, pitfalls, and current project preferences.
12- Keep this file accurate and current. Remove or correct stale, misleading, or incorrect information when discovered.
13- If information is temporary or uncertain, label it clearly rather than presenting it as permanent fact.
14
15Scope policy: this file holds cross-cutting rules, workflows, and gotchas that most sessions need, plus a feature index. Keep it around 30 KB. Feature deep-dives live in `docs/<topic>.md`: before working on a feature listed in the index, read its doc; when finishing feature work, update that doc and keep the index entry here to one or two lines (where it lives + the non-obvious constraint). Cross-cutting rules and new gotchas still land here directly. When a change makes anything stale, here or in a linked doc, update it in the same change.
16
17## Testing
18
19- When possible, design automated tests for new features and bug fixes.
20- Run relevant automated tests after finishing changes to guard against regressions.
21- If tests cannot be run or do not exist, state that clearly in the handoff and describe any manual verification performed.
22- Always finish project changes by building the Release configuration: `dotnet build .\UGTLive.sln --configuration Release`.
23- If a running UGTLive process prevents the Release build, capture its executable/command line, stop it, complete the build, and restart it afterward. Do not start UGTLive if it was not running before the build.
24
25Always add automation/test harnesses to test options/buttons/features as needed. Document them.
26
27## Cloud LLM Model Maintenance
28
29- Cloud and CLI model picker presets live in `src/SettingsWindow.xaml`; their fallback/default values live in `src/ConfigManager.cs`, `src/ConfigManager.Translation.cs`, and `src/SettingsWindow.TranslationSettings.cs`.
30- Subscription-backed CLI providers display as `Anthropic Sub`, `OpenAI Sub`, and `Gemini CLI (Enterprise)`, but their stable internal IDs remain `ClaudeCli`, `CodexCli`, and `GeminiCli`; use `ComboBoxItem.Tag` for the internal ID. Google ended personal/free/AI Pro/AI Ultra access through Gemini CLI on June 18, 2026; do not replace it with Antigravity CLI until `agy -p` reliably exposes captured stdout to Windows parent processes (see `docs/settings-connection-tests.md`).
31- Keep provider-specific capability handling in the matching translation service. In particular, Anthropic model generations use different manual/adaptive thinking request shapes.
32- Verify model IDs and request compatibility against current official provider documentation. Verify OpenRouter-prefixed slugs against its `/api/v1/models` catalog before adding presets.
33
34## Feature Index
35
36- Settings API/model/voice tests: see `docs/settings-connection-tests.md`. UI buttons and `--test-settings-connection` must continue to call the shared `SettingsConnectionTester` implementation.
37- OpenAI All In One Snap translation: see `docs/openai-all-in-one.md`. It is a Snap-only, visual-only `gpt-image-2` Image Edits path; Auto and realtime processing must remain on the standard OCR pipeline.
38
39
40## Security
41
42- Never commit sensitive data, including credentials, tokens, passwords, private keys, cookies, customer data, personal data, or machine-specific authentication material.
43- If an AI assistant needs authentication data or other secrets for local work, use `agents_secret.md` for those notes.
44- `agents_secret.md` must stay ignored by git and must not be committed.
45- Do not put secrets in commit messages, logs, issue text, pull request descriptions, generated docs, or other tracked files.
46- Configuration logging must pass key names through `ConfigManager.IsSensitiveConfigKey`; never print raw secret values in startup or harness output.
47- Before committing, review staged changes for accidental secrets.
48
49## Git
50
51- Never add OpenAI/Codex/Claude etc as a co-author on git commits.
52- NEVER `git commit` unless explicitly told to commit.
53- NEVER `git push` unless explicitly told to push. "Commit" means commit
54 locally only; committing is not permission to push.
55
SethRobinson/UGTLive · .cursor/rules/architecture-patterns.mdc
@@ +1 @@
1---
2description: Architecture patterns and project structure guidelines
3globs: ["**/*.cs"]
4alwaysApply: false
5---
6
7# Architecture Patterns
8
9## Project Structure
10
11### Directory Organization
12```
13src/
14 - Core application files (App.xaml, Logic.cs, ConfigManager.cs)
15 - Window classes (MainWindow, MonitorWindow, ChatBoxWindow, SettingsWindow, etc.)
16 - Translation services (Gemini, ChatGPT, Ollama, GoogleTranslate, LlamaCpp)
17 - OCR services (WindowsOCRManager, GoogleVisionOCRService)
18 - Managers (UniversalBlockDetector, LogManager, HotkeyManager, PythonServicesManager, AudioPlaybackManager, etc.)
19 - Utilities (TextObject, TranslationEventArgs, etc.)
20app/
21 - Compiled binaries
22 - services/ (Python OCR services - EasyOCR, MangaOCR, PaddleOCR, DocTR)
23 - shared/ (Shared Python utilities)
24 - util/ (Python installation utilities)
25 - EasyOCR/, MangaOCR/, PaddleOCR/, DocTR/ (Individual service directories)
26 - media/ (Resources)
27```
28
29### File Naming
30- One class per file
31- File name matches class name
32- XAML files: `WindowName.xaml` and `WindowName.xaml.cs`
33
34## Design Patterns
35
36### Singleton Pattern
37Used for core managers:
38- `ConfigManager.Instance`
39- `Logic.Instance`
40- `UniversalBlockDetector.Instance` - Advanced text block detection (replaces BlockDetectionManager)
41- `LogManager.Instance`
42- `PythonServicesManager.Instance` - Manages Python OCR services
43- `HotkeyManager.Instance` - Manages global keyboard shortcuts (replaces KeyboardShortcuts)
44- `AudioPlaybackManager.Instance` - Manages audio playback
45- `AudioPreloadService.Instance` - Preloads TTS audio
46- `ErrorPopupManager` - Static class for error popups
47- `GamepadManager.Instance` - Manages gamepad input
48- `WebViewEnvironmentManager` - Static class for WebView2 environment
49
50**Implementation:**
51```csharp
52private static ConfigManager? _instance;
53
54public static ConfigManager Instance
55{
56 get
57 {
58 if (_instance == null)
59 {
60 _instance = new ConfigManager();
61 }
62 return _instance;
63 }
64}
65
66private ConfigManager() { }
67```
68
69### Factory Pattern
70Used for creating service instances:
71
72```csharp
73public static class TranslationServiceFactory
74{
75 public static ITranslationService CreateService(string serviceName)
76 {
77 return serviceName switch
78 {
79 "Gemini" => new GeminiTranslationService(),
80 "ChatGPT" => new ChatGptTranslationService(),
81 "Ollama" => new OllamaTranslationService(),
82 "Google Translate" => new GoogleTranslateService(),
83 "llama.cpp" => new LlamaCppTranslationService(),
84 _ => throw new ArgumentException(...)
85 };
86 }
87}
88```
89
90### Strategy Pattern
91Translation services implement common interface:
92
93```csharp
94public interface ITranslationService
95{
96 Task<TranslationResult?> TranslateAsync(
97 string sourceText,
98 string targetLanguage,
99 string context);
100}
101```
102
103## Separation of Concerns
104
105### UI Layer
106- XAML files define UI structure
107- Code-behind handles UI events
108- Minimal business logic in UI code
109
110### Business Logic Layer
111- `Logic.cs` - Core translation workflow
112- `UniversalBlockDetector.cs` - Advanced text block detection and grouping
113- Service classes - External API integration
114
115### Data Layer
116- `ConfigManager.cs` - Configuration persistence
117- File-based storage (config.txt, service-specific configs)
118
119## Dependency Management
120
121### Service Dependencies
122Services depend on ConfigManager, not each other:
123
124```csharp
125public class GeminiTranslationService
126{
127 private readonly string _apiKey;
128
129 public GeminiTranslationService()
130 {
131 _apiKey = ConfigManager.Instance.GetGeminiApiKey();
132 }
133}
134```
135
136### Manager Dependencies
137Managers can depend on other managers:
138
139```csharp
140public class Logic
141{
142 private readonly ConfigManager _configManager;
143 private readonly UniversalBlockDetector _blockDetector;
144
145 public Logic()
146 {
147 _configManager = ConfigManager.Instance;
148 _blockDetector = UniversalBlockDetector.Instance;
149 }
150}
151```
152
153## Communication Patterns
154
155### Window Communication
156Windows communicate through Logic.Instance:
157
158```csharp
159// In ChatBoxWindow
160Logic.Instance.OnTranslationReceived += HandleTranslation;
161
162// In Logic
163public event EventHandler<TranslationEventArgs>? OnTranslationReceived;
164```
165
166### Event-Driven Architecture
167Use events for loose coupling:
168
169```csharp
170public class TranslationEventArgs : EventArgs
171{
172 public string TranslatedText { get; set; } = "";
173 public string SourceText { get; set; } = "";
174}
175```
176
177### Hotkey System
178Hotkeys managed through HotkeyManager events:
179
180```csharp
181HotkeyManager.Instance.StartStopRequested += OnStartStopRequested;
182HotkeyManager.Instance.MonitorToggleRequested += OnMonitorToggleRequested;
183```
184
185## Resource Management
186
187### Disposable Resources
188Implement IDisposable for resources:
189
190```csharp
191public class ResourceManager : IDisposable
192{
193 private bool _disposed = false;
194
195 public void Dispose()
196 {
197 Dispose(true);
198 GC.SuppressFinalize(this);
199 }
200
201 protected virtual void Dispose(bool disposing)
202 {
203 if (!_disposed)
204 {
205 if (disposing)
206 {
207 // Dispose managed resources
208 }
209 // Dispose unmanaged resources
210 _disposed = true;
211 }
212 }
213}
214```
215
216### Using Statements
217Always use `using` for disposable resources:
218
219```csharp
220using (var bitmap = new Bitmap(width, height))
221{
222 // Use bitmap
223} // Automatically disposed
224
225// Or with async
226using var httpClient = new HttpClient();
227var response = await httpClient.GetAsync(url);
228```
229
230## State Management
231
232### Application State
233State stored in ConfigManager:
234
235```csharp
236// Current translation service
237_currentTranslationService = ConfigManager.Instance.GetCurrentTranslationService();
238
239// Window positions
240var pos = ConfigManager.Instance.GetWindowPosition("ChatBox");
241```
242
243### Runtime State
244Runtime state in Logic or window classes:
245
246```csharp
247private bool _isProcessing = false;
248private List<TextObject> _currentTextBlocks = new();
249```
250
251## Error Propagation
252
253### Error Handling Strategy
254- Services return null on error
255- Log errors using LogManager
256- Show user-friendly messages via ErrorPopupManager
257- Don't crash the application
258
259```csharp
260public async Task<Result?> ProcessAsync()
261{
262 try
263 {
264 return await DoWorkAsync();
265 }
266 catch (Exception ex)
267 {
268 LogManager.Instance.LogError("Process failed", ex);
269 ErrorPopupManager.ShowError("Process failed", ex.Message);
270 return null; // Return null instead of throwing
271 }
272}
273```
274
275## Extension Points
276
277### Adding New Translation Service
2781. Implement `ITranslationService`
2792. Add config keys to ConfigManager
2803. Update TranslationServiceFactory
2814. Add UI in SettingsWindow
282
283### Adding New OCR Method
2841. Add method name to `SupportedOcrMethods` in ConfigManager
2852. Implement processing logic
286 - For Python services: Add service directory in `app/services/` with `service_config.txt` and `server.py`
287 - For built-in OCR: Implement in appropriate manager class (e.g., WindowsOCRManager, GoogleVisionOCRService)
2883. Update OCR selection UI
2894. Add configuration options
290
291### Adding New Python OCR Service
2921. Create service directory in `app/services/` (e.g., `app/services/NewOCR/`)
2932. Create `service_config.txt` with required fields:
294 - `service_name` (ASCII only, no spaces)
295 - `venv_name` (ASCII only, e.g., `ugt_newocr`)
296 - `port` (unique port number)
297 - `description`, `version`, `author`, `github_url`, etc.
2983. Create `server.py` implementing FastAPI endpoints:
299 - `/process` - Process images
300 - `/info` - Service information
301 - `/health` - Health check
302 - `/shutdown` - Graceful shutdown
3034. Create batch scripts: `Install.bat`, `RunServer.bat`, `DiagnosticTest.bat`, `Uninstall.bat`
3045. Service will be automatically discovered by `PythonServicesManager` on app startup
305
306## Performance Considerations
307
308### Lazy Initialization
309Initialize expensive resources on demand:
310
311```csharp
312private HttpClient? _httpClient;
313
314private HttpClient HttpClient
315{
316 get
317 {
318 if (_httpClient == null)
319 {
320 _httpClient = new HttpClient();
321 }
322 return _httpClient;
323 }
324}
325```
326
327### Caching
328Cache expensive operations:
329
330```csharp
331private Dictionary<string, TranslationResult> _translationCache = new();
332
333public TranslationResult? GetCachedTranslation(string text)
334{
335 if (_translationCache.TryGetValue(text, out var cached))
336 {
337 return cached;
338 }
339 return null;
340}
341```
342
343## Threading Model
344
345### UI Thread
346- All UI updates on UI thread
347- Use Dispatcher.Invoke for cross-thread updates
348- Long operations off UI thread
349
350### Background Threads
351- OCR processing on background thread
352- Network requests async/await
353- Screen capture on timer thread
354
355## Module Boundaries
356
357### Service Boundaries
358Services are independent modules:
359- Each service in own file
360- No direct dependencies between services
361- Communicate through interfaces
362
363### Manager Boundaries
364Managers provide cross-cutting concerns:
365- ConfigManager - Configuration
366- LogManager - Logging
367- UniversalBlockDetector - Text processing
368- HotkeyManager - Keyboard shortcuts
369- AudioPlaybackManager - Audio playback
370
371## Testing Architecture
372
373### Testable Components
374- Business logic separate from UI
375- Services implement interfaces
376- Static utility methods where possible
377
378### Mock-Friendly Design
379```csharp
380// Use interface for testability
381public interface ITranslationService
382{
383 Task<TranslationResult?> TranslateAsync(...);
384}
385
386// Can be mocked in tests
387var mockService = new Mock<ITranslationService>();
388```
389
390## Version Management
391
392### Version Updates
393Update version in three places:
3941. `SplashManager.cs` - `CurrentVersion` constant
3952. `media/latest_version_checker.json` - `latest_version` field
3963. `README.md` - Version badge and history entry
397
398### Version Format
399- Use double/float (e.g., 0.60)
400- Increment by 0.01 for minor updates
401- Increment by 0.10 for major features
402
403## Build Configuration
404
405### Output Structure
406- Debug: `ugtlive_debug.exe` in `app/`
407- Release: `ugtlive.exe` in `app/`
408- All dependencies in `app/` directory
409
410### Dependencies
411- .NET 8.0 Windows
412- WPF and Windows Forms
413- NAudio for audio
414- WebView2 for web content
415
@@ −1 +1 @@
1−# AGENTS.md
1+---
2+description: Architecture patterns and project structure guidelines
3+globs: ["**/*.cs"]
4+alwaysApply: false
5+---
26
3−Project operating instructions for AI assistants working in this repository.
7+# Architecture Patterns
48
5−## Shared Project Memory
9+## Project Structure
610
7−- At the start of each new task or thread involving this repository, read this file before inspecting files, running commands, making a plan, or taking any other project action.
8−- Treat follow-up replies in the same continuous task as part of that task. Do not reread this file unless the repository or working directory changes, this file is modified, or its instructions are no longer available in context.
9−- Treat this file as the shared project memory for AI assistants.
10−- Do not rely on vendor-specific, proprietary, or hidden memory systems for project facts, preferences, or operating instructions. (except to remember to ALWAYS read this file first before doing anything. Remember that.)
11−- Update this file with important repo-specific information learned during work, including build commands, test commands, conventions, decisions, pitfalls, and current project preferences.
12−- Keep this file accurate and current. Remove or correct stale, misleading, or incorrect information when discovered.
13−- If information is temporary or uncertain, label it clearly rather than presenting it as permanent fact.
11+### Directory Organization
12+```
13+src/
14+ - Core application files (App.xaml, Logic.cs, ConfigManager.cs)
15+ - Window classes (MainWindow, MonitorWindow, ChatBoxWindow, SettingsWindow, etc.)
16+ - Translation services (Gemini, ChatGPT, Ollama, GoogleTranslate, LlamaCpp)
17+ - OCR services (WindowsOCRManager, GoogleVisionOCRService)
18+ - Managers (UniversalBlockDetector, LogManager, HotkeyManager, PythonServicesManager, AudioPlaybackManager, etc.)
19+ - Utilities (TextObject, TranslationEventArgs, etc.)
20+app/
21+ - Compiled binaries
22+ - services/ (Python OCR services - EasyOCR, MangaOCR, PaddleOCR, DocTR)
23+ - shared/ (Shared Python utilities)
24+ - util/ (Python installation utilities)
25+ - EasyOCR/, MangaOCR/, PaddleOCR/, DocTR/ (Individual service directories)
26+ - media/ (Resources)
27+```
1428
15−Scope policy: this file holds cross-cutting rules, workflows, and gotchas that most sessions need, plus a feature index. Keep it around 30 KB. Feature deep-dives live in `docs/<topic>.md`: before working on a feature listed in the index, read its doc; when finishing feature work, update that doc and keep the index entry here to one or two lines (where it lives + the non-obvious constraint). Cross-cutting rules and new gotchas still land here directly. When a change makes anything stale, here or in a linked doc, update it in the same change.
29+### File Naming
30+- One class per file
31+- File name matches class name
32+- XAML files: `WindowName.xaml` and `WindowName.xaml.cs`
1633
17−## Testing
34+## Design Patterns
1835
19−- When possible, design automated tests for new features and bug fixes.
20−- Run relevant automated tests after finishing changes to guard against regressions.
21−- If tests cannot be run or do not exist, state that clearly in the handoff and describe any manual verification performed.
22−- Always finish project changes by building the Release configuration: `dotnet build .\UGTLive.sln --configuration Release`.
23−- If a running UGTLive process prevents the Release build, capture its executable/command line, stop it, complete the build, and restart it afterward. Do not start UGTLive if it was not running before the build.
36+### Singleton Pattern
37+Used for core managers:
38+- `ConfigManager.Instance`
39+- `Logic.Instance`
40+- `UniversalBlockDetector.Instance` - Advanced text block detection (replaces BlockDetectionManager)
41+- `LogManager.Instance`
42+- `PythonServicesManager.Instance` - Manages Python OCR services
43+- `HotkeyManager.Instance` - Manages global keyboard shortcuts (replaces KeyboardShortcuts)
44+- `AudioPlaybackManager.Instance` - Manages audio playback
45+- `AudioPreloadService.Instance` - Preloads TTS audio
46+- `ErrorPopupManager` - Static class for error popups
47+- `GamepadManager.Instance` - Manages gamepad input
48+- `WebViewEnvironmentManager` - Static class for WebView2 environment
2449
25−Always add automation/test harnesses to test options/buttons/features as needed. Document them.
50+**Implementation:**
51+```csharp
52+private static ConfigManager? _instance;
2653
27−## Cloud LLM Model Maintenance
54+public static ConfigManager Instance
55+{
56+ get
57+ {
58+ if (_instance == null)
59+ {
60+ _instance = new ConfigManager();
61+ }
62+ return _instance;
63+ }
64+}
2865
29−- Cloud and CLI model picker presets live in `src/SettingsWindow.xaml`; their fallback/default values live in `src/ConfigManager.cs`, `src/ConfigManager.Translation.cs`, and `src/SettingsWindow.TranslationSettings.cs`.
30−- Subscription-backed CLI providers display as `Anthropic Sub`, `OpenAI Sub`, and `Gemini CLI (Enterprise)`, but their stable internal IDs remain `ClaudeCli`, `CodexCli`, and `GeminiCli`; use `ComboBoxItem.Tag` for the internal ID. Google ended personal/free/AI Pro/AI Ultra access through Gemini CLI on June 18, 2026; do not replace it with Antigravity CLI until `agy -p` reliably exposes captured stdout to Windows parent processes (see `docs/settings-connection-tests.md`).
31−- Keep provider-specific capability handling in the matching translation service. In particular, Anthropic model generations use different manual/adaptive thinking request shapes.
32−- Verify model IDs and request compatibility against current official provider documentation. Verify OpenRouter-prefixed slugs against its `/api/v1/models` catalog before adding presets.
66+private ConfigManager() { }
67+```
3368
34−## Feature Index
69+### Factory Pattern
70+Used for creating service instances:
3571
36−- Settings API/model/voice tests: see `docs/settings-connection-tests.md`. UI buttons and `--test-settings-connection` must continue to call the shared `SettingsConnectionTester` implementation.
37−- OpenAI All In One Snap translation: see `docs/openai-all-in-one.md`. It is a Snap-only, visual-only `gpt-image-2` Image Edits path; Auto and realtime processing must remain on the standard OCR pipeline.
72+```csharp
73+public static class TranslationServiceFactory
74+{
75+ public static ITranslationService CreateService(string serviceName)
76+ {
77+ return serviceName switch
78+ {
79+ "Gemini" => new GeminiTranslationService(),
80+ "ChatGPT" => new ChatGptTranslationService(),
81+ "Ollama" => new OllamaTranslationService(),
82+ "Google Translate" => new GoogleTranslateService(),
83+ "llama.cpp" => new LlamaCppTranslationService(),
84+ _ => throw new ArgumentException(...)
85+ };
86+ }
87+}
88+```
3889
90+### Strategy Pattern
91+Translation services implement common interface:
3992
40−## Security
93+```csharp
94+public interface ITranslationService
95+{
96+ Task<TranslationResult?> TranslateAsync(
97+ string sourceText,
98+ string targetLanguage,
99+ string context);
100+}
101+```
41102
42−- Never commit sensitive data, including credentials, tokens, passwords, private keys, cookies, customer data, personal data, or machine-specific authentication material.
43−- If an AI assistant needs authentication data or other secrets for local work, use `agents_secret.md` for those notes.
44−- `agents_secret.md` must stay ignored by git and must not be committed.
45−- Do not put secrets in commit messages, logs, issue text, pull request descriptions, generated docs, or other tracked files.
46−- Configuration logging must pass key names through `ConfigManager.IsSensitiveConfigKey`; never print raw secret values in startup or harness output.
47−- Before committing, review staged changes for accidental secrets.
103+## Separation of Concerns
48104
49−## Git
105+### UI Layer
106+- XAML files define UI structure
107+- Code-behind handles UI events
108+- Minimal business logic in UI code
50109
51−- Never add OpenAI/Codex/Claude etc as a co-author on git commits.
52−- NEVER `git commit` unless explicitly told to commit.
53−- NEVER `git push` unless explicitly told to push. "Commit" means commit
54− locally only; committing is not permission to push.
110+### Business Logic Layer
111+- `Logic.cs` - Core translation workflow
112+- `UniversalBlockDetector.cs` - Advanced text block detection and grouping
113+- Service classes - External API integration
114+
115+### Data Layer
116+- `ConfigManager.cs` - Configuration persistence
117+- File-based storage (config.txt, service-specific configs)
118+
119+## Dependency Management
120+
121+### Service Dependencies
122+Services depend on ConfigManager, not each other:
123+
124+```csharp
125+public class GeminiTranslationService
126+{
127+ private readonly string _apiKey;
128+
129+ public GeminiTranslationService()
130+ {
131+ _apiKey = ConfigManager.Instance.GetGeminiApiKey();
132+ }
133+}
134+```
135+
136+### Manager Dependencies
137+Managers can depend on other managers:
138+
139+```csharp
140+public class Logic
141+{
142+ private readonly ConfigManager _configManager;
143+ private readonly UniversalBlockDetector _blockDetector;
144+
145+ public Logic()
146+ {
147+ _configManager = ConfigManager.Instance;
148+ _blockDetector = UniversalBlockDetector.Instance;
149+ }
150+}
151+```
152+
153+## Communication Patterns
154+
155+### Window Communication
156+Windows communicate through Logic.Instance:
157+
158+```csharp
159+// In ChatBoxWindow
160+Logic.Instance.OnTranslationReceived += HandleTranslation;
161+
162+// In Logic
163+public event EventHandler<TranslationEventArgs>? OnTranslationReceived;
164+```
165+
166+### Event-Driven Architecture
167+Use events for loose coupling:
168+
169+```csharp
170+public class TranslationEventArgs : EventArgs
171+{
172+ public string TranslatedText { get; set; } = "";
173+ public string SourceText { get; set; } = "";
174+}
175+```
176+
177+### Hotkey System
178+Hotkeys managed through HotkeyManager events:
179+
180+```csharp
181+HotkeyManager.Instance.StartStopRequested += OnStartStopRequested;
182+HotkeyManager.Instance.MonitorToggleRequested += OnMonitorToggleRequested;
183+```
184+
185+## Resource Management
186+
187+### Disposable Resources
188+Implement IDisposable for resources:
189+
190+```csharp
191+public class ResourceManager : IDisposable
192+{
193+ private bool _disposed = false;
194+
195+ public void Dispose()
196+ {
197+ Dispose(true);
198+ GC.SuppressFinalize(this);
199+ }
200+
201+ protected virtual void Dispose(bool disposing)
202+ {
203+ if (!_disposed)
204+ {
205+ if (disposing)
206+ {
207+ // Dispose managed resources
208+ }
209+ // Dispose unmanaged resources
210+ _disposed = true;
211+ }
212+ }
213+}
214+```
215+
216+### Using Statements
217+Always use `using` for disposable resources:
218+
219+```csharp
220+using (var bitmap = new Bitmap(width, height))
221+{
222+ // Use bitmap
223+} // Automatically disposed
224+
225+// Or with async
226+using var httpClient = new HttpClient();
227+var response = await httpClient.GetAsync(url);
228+```
229+
230+## State Management
231+
232+### Application State
233+State stored in ConfigManager:
234+
235+```csharp
236+// Current translation service
237+_currentTranslationService = ConfigManager.Instance.GetCurrentTranslationService();
238+
239+// Window positions
240+var pos = ConfigManager.Instance.GetWindowPosition("ChatBox");
241+```
242+
243+### Runtime State
244+Runtime state in Logic or window classes:
245+
246+```csharp
247+private bool _isProcessing = false;
248+private List<TextObject> _currentTextBlocks = new();
249+```
250+
251+## Error Propagation
252+
253+### Error Handling Strategy
254+- Services return null on error
255+- Log errors using LogManager
256+- Show user-friendly messages via ErrorPopupManager
257+- Don't crash the application
258+
259+```csharp
260+public async Task<Result?> ProcessAsync()
261+{
262+ try
263+ {
264+ return await DoWorkAsync();
265+ }
266+ catch (Exception ex)
267+ {
268+ LogManager.Instance.LogError("Process failed", ex);
269+ ErrorPopupManager.ShowError("Process failed", ex.Message);
270+ return null; // Return null instead of throwing
271+ }
272+}
273+```
274+
275+## Extension Points
276+
277+### Adding New Translation Service
278+1. Implement `ITranslationService`
279+2. Add config keys to ConfigManager
280+3. Update TranslationServiceFactory
281+4. Add UI in SettingsWindow
282+
283+### Adding New OCR Method
284+1. Add method name to `SupportedOcrMethods` in ConfigManager
285+2. Implement processing logic
286+ - For Python services: Add service directory in `app/services/` with `service_config.txt` and `server.py`
287+ - For built-in OCR: Implement in appropriate manager class (e.g., WindowsOCRManager, GoogleVisionOCRService)
288+3. Update OCR selection UI
289+4. Add configuration options
290+
291+### Adding New Python OCR Service
292+1. Create service directory in `app/services/` (e.g., `app/services/NewOCR/`)
293+2. Create `service_config.txt` with required fields:
294+ - `service_name` (ASCII only, no spaces)
295+ - `venv_name` (ASCII only, e.g., `ugt_newocr`)
296+ - `port` (unique port number)
297+ - `description`, `version`, `author`, `github_url`, etc.
298+3. Create `server.py` implementing FastAPI endpoints:
299+ - `/process` - Process images
300+ - `/info` - Service information
301+ - `/health` - Health check
302+ - `/shutdown` - Graceful shutdown
303+4. Create batch scripts: `Install.bat`, `RunServer.bat`, `DiagnosticTest.bat`, `Uninstall.bat`
304+5. Service will be automatically discovered by `PythonServicesManager` on app startup
305+
306+## Performance Considerations
307+
308+### Lazy Initialization
309+Initialize expensive resources on demand:
310+
311+```csharp
312+private HttpClient? _httpClient;
313+
314+private HttpClient HttpClient
315+{
316+ get
317+ {
318+ if (_httpClient == null)
319+ {
320+ _httpClient = new HttpClient();
321+ }
322+ return _httpClient;
323+ }
324+}
325+```
326+
327+### Caching
328+Cache expensive operations:
329+
330+```csharp
331+private Dictionary<string, TranslationResult> _translationCache = new();
332+
333+public TranslationResult? GetCachedTranslation(string text)
334+{
335+ if (_translationCache.TryGetValue(text, out var cached))
336+ {
337+ return cached;
338+ }
339+ return null;
340+}
341+```
342+
343+## Threading Model
344+
345+### UI Thread
346+- All UI updates on UI thread
347+- Use Dispatcher.Invoke for cross-thread updates
348+- Long operations off UI thread
349+
350+### Background Threads
351+- OCR processing on background thread
352+- Network requests async/await
353+- Screen capture on timer thread
354+
355+## Module Boundaries
356+
357+### Service Boundaries
358+Services are independent modules:
359+- Each service in own file
360+- No direct dependencies between services
361+- Communicate through interfaces
362+
363+### Manager Boundaries
364+Managers provide cross-cutting concerns:
365+- ConfigManager - Configuration
366+- LogManager - Logging
367+- UniversalBlockDetector - Text processing
368+- HotkeyManager - Keyboard shortcuts
369+- AudioPlaybackManager - Audio playback
370+
371+## Testing Architecture
372+
373+### Testable Components
374+- Business logic separate from UI
375+- Services implement interfaces
376+- Static utility methods where possible
377+
378+### Mock-Friendly Design
379+```csharp
380+// Use interface for testability
381+public interface ITranslationService
382+{
383+ Task<TranslationResult?> TranslateAsync(...);
384+}
385+
386+// Can be mocked in tests
387+var mockService = new Mock<ITranslationService>();
388+```
389+
390+## Version Management
391+
392+### Version Updates
393+Update version in three places:
394+1. `SplashManager.cs` - `CurrentVersion` constant
395+2. `media/latest_version_checker.json` - `latest_version` field
396+3. `README.md` - Version badge and history entry
397+
398+### Version Format
399+- Use double/float (e.g., 0.60)
400+- Increment by 0.01 for minor updates
401+- Increment by 0.10 for major features
402+
403+## Build Configuration
404+
405+### Output Structure
406+- Debug: `ugtlive_debug.exe` in `app/`
407+- Release: `ugtlive.exe` in `app/`
408+- All dependencies in `app/` directory
409+
410+### Dependencies
411+- .NET 8.0 Windows
412+- WPF and Windows Forms
413+- NAudio for audio
414+- WebView2 for web content
55415
