Technical Debt Tracker¶
Last Updated: 2026-01-29 Version: v1.15.1 (ppxaide TUI performance fixes, VSCode cleanup)
This document tracks identified technical debt and refactoring opportunities in the ppxai codebase. Items are removed as they are addressed.
Critical Priority¶
1. Global State Management¶
Status: ✅ Completed (v1.13.10) Files: ppxai/server/http.py, ppxai/server/session_manager.py
Resolution: Refactored to SessionManager class with:
- Thread-safe singleton pattern using threading.Lock for creation
- Async-safe operations using asyncio.Lock for session access
- Centralized session, consent, and activity tracking
- Proper initialization/shutdown via FastAPI lifespan
- Added /health and /ready endpoints for container orchestration
New Files Created:
- ppxai/server/session_manager.py - SessionManager class (467 lines)
Changes to http.py:
- Removed global variables: sessions, default_engine, default_lock, pending_consent_requests, etc.
- Added single session_manager: SessionManager global
- All endpoints now use await get_or_create_session() for thread-safe session access
2. Monolithic Files¶
Status: Mostly Addressed (v1.13.10)
| File | Lines | Issue | Status |
|---|---|---|---|
| ppxai/commands/handler.py | 507 | CommandHandler class (legacy methods commented) | ✅ Command Factory |
| ppxai/server/http.py | 2,247 | HTTP + session + consent mixed | ✅ SessionManager extracted |
| ppxai/engine/client.py | 1,311 | Core logic, providers, tools, sessions | ✅ Refactored (36% reduction) |
| ppxai/config/ | ~700 | Config package with store, loader, public API | ✅ ConfigStore pattern |
| vscode-extension/src/chatPanel.ts | 2,773 | Event/command handling | ✅ Phase 4 Complete |
| vscode-extension/src/handlers/ | 1,658 | Extracted handlers module | ✅ New (Phases 2-4) |
client.py Refactoring - ✅ Completed (v1.13.10):
See DESIGN-CLIENT-REFACTOR.md for full details:
- Phase 1: Config cleanup - Created config/defaults.py, removed lazy imports
- Phase 2: Tool parser - Extracted to tools/parser.py (308 lines)
- Phase 3: Shell classify - Moved classify_shell_command() to consent.py
- Phase 4: Chat extraction - Created engine/chat.py with ChatContext Protocol (433 lines)
- Phase 5: Interface cleanup - Removed session wrappers, use engine.session directly
commands.py Refactoring - ✅ Completed (v1.13.10):
Migrated to Command Factory pattern in ppxai/commands/ package:
- factory.py - CommandSpec, CommandFactory registry with self-registration
- session.py - /save, /export, /sessions, /load
- provider.py - /model, /provider, /autoroute
- system.py - /help, /theme, /status, /spec
- coding.py - /generate, /test, /docs, /implement, /debug, /explain, /convert
- utility.py - /cd, /pwd, /config, /debug_log, /context
- tools.py - /tools, /usage
- display.py - /show
- agent.py - /agent, /undo, /checkpoint
- Legacy methods in handler.py commented with deprecation notice (removal in v1.14.x)
chatPanel.ts Refactoring - ✅ Completed (v1.13.10):
See DESIGN-CHATPANEL-REFACTOR.md for full details:
- Phase 1: Extracted webview CSS/JS to media/webview/ (41% reduction, 5,123→3,045 lines)
- Phase 2: Command handlers with IoC pattern (handlers/commands.ts, types.ts)
- Phase 3: EventBus architecture (eventBus.ts, stream.ts, UI subscriptions)
- Phase 4: State machine + consent handlers (agentStateMachine.ts, consent.ts)
Result: chatPanel.ts 2,773 lines + handlers/ 1,658 lines = clean separation of concerns
config.py Package Conversion - ✅ Completed (v1.13.10):
Converted monolithic config.py (1,352 lines) to config/ package (~700 lines):
- config/store.py - Thread-safe ConfigStore singleton with double-check locking
- config/loader.py - Config loading, validation, environment handling
- config/__init__.py - Full public API with module-level __getattr__
Key improvements:
- Thread-safe and asyncio-safe for containerized deployments
- ConfigStore.set_for_testing() replaces direct _config patching in tests
- Module-level __getattr__ provides lazy PROVIDERS and MODELS access
- Removed legacy globals: MODEL_PROVIDER, set_active_provider()
- Added get_default_provider() function for runtime provider resolution
3. Silent Error Handling¶
Status: ✅ Completed (v1.13.10) Scope: Reviewed 48 instances of silent error handling across 8 files
Resolution: Applied selective logging based on value:
- 22 instances now log with logger.debug() or logger.warning()
- 11 instances kept silent (intentional fallbacks, expected errors)
- 15 instances in LOW priority files left as-is (trial-error detection, cleanup)
Key Changes:
- Fixed 2 bare except: clauses in client.py (security risk - caught KeyboardInterrupt)
- Added logger.warning() for invalid regex patterns in consent.py (security config)
- Added logger.warning() for auto-save failures and corrupted session files
- Added logger.debug() for checkpoint, session restore, and tool status errors
Files Modified:
- ppxai/usage.py - Usage data loading
- ppxai/commands.py - Tool/consent status, file search, git status
- ppxai/server/http.py - Consent mode retrieval
- ppxai/engine/client.py - Checkpoint restore, regex patterns, shell consent
- ppxai/common/consent.py - Shell command pattern compilation
- ppxai/main.py - Session restore, auto-save
- ppxai/engine/session.py - Corrupted session files
- ppxai/checkpoint.py - Checkpoint creation
High Priority¶
4. Code Duplication - Container Tools¶
Status: ✅ Completed (v1.13.10) File: ppxai/engine/tools/builtin/container.py (738 lines)
Resolution: Refactored to use inheritance hierarchy:
- CLITool - Base class for read-only CLI tools
- ConsentCLITool - Base class for tools requiring user consent
- DockerTool / DockerConsentTool - Docker/Podman specific bases
- KubeTool / KubeConsentTool - Kubernetes specific bases
Each tool now only defines build_command() method and metadata, reducing boilerplate by ~40%.
5. Code Duplication - Consent Manager¶
Status: ✅ Completed (v1.13.10) File: ppxai/common/consent.py
Resolution: Extracted BaseConsentManager class with shared logic:
- All state initialization (files, commands, patterns)
- Pattern loading and command classification
- Status reporting and non-prompting approval checks
- Decision processing helpers
Both ConsentManager (async) and SyncConsentManager now inherit from BaseConsentManager, reducing duplication by ~100 lines (708 → 609 lines, 14% reduction).
6. Import Structure¶
Status: ✅ Refactored (v1.13.10)
Pattern: The codebase follows a DAG (Directed Acyclic Graph) import structure:
1. TYPE_CHECKING - For type hints in builtin tools (required to avoid actual cycles)
2. Clean leaf modules - config.py, themes.py, types.py have no ppxai imports
3. Top-level imports - commands.py now uses standard top-level imports
Refactoring Done:
- Removed unnecessary lazy imports from commands.py (moved to top-level)
- Verified no circular dependencies exist in the codebase
- Updated docs/ARCHITECTURE.md with accurate DAG documentation
Note: The only pattern truly needed is TYPE_CHECKING in tools/builtin/*.py.
Future Improvement: A Tool Factory pattern could eliminate TYPE_CHECKING entirely and enable dynamic tool loading. See DESIGN-TOOL-FACTORY.md for detailed analysis.
7. Dangerous eval() Usage¶
Status: ✅ Completed (v1.13.10) File: ppxai/engine/tools/builtin/calculator.py
Resolution: Replaced eval() with AST-based safe evaluation:
- Uses ast.parse() to parse expressions into AST
- Custom _safe_eval() function walks the AST
- Only supports numeric constants, binary ops (+,-,,/,//,%,*), and unary ops
- Rejects function calls, name references, and any other constructs
- Better error messages (division by zero, syntax errors, unsupported expressions)
Medium Priority¶
8. Missing Type Hints¶
Status: ✅ Partially Addressed (v1.13.10)
TypeScript (resolved):
- Created FileConsentRequest, ShellConsentRequest interfaces in httpClient.ts
- Added EventMetadata interface replacing metadata?: any
- Added ConsentResponse type for consent response values
- Updated chatPanel.ts to use new types
Remaining (low priority):
- backend.ts:25, 64 - generic result types (truly polymorphic)
- Python provider methods - already have good type coverage in base.py
9. Inconsistent Error Handling in HTTP Endpoints¶
Status: ✅ Partially Addressed (v1.13.10) File: ppxai/server/http.py
Resolution (v1.13.10):
- Removed unused JSONResponse import
- Standardized static file 404 error messages to include requested filename
- Fixed string concatenation in error details (use f-strings consistently)
- All error responses now use HTTPException exclusively (45 occurrences)
Remaining items: - Silent pass patterns for expected errors (intentional, kept for graceful degradation)
Original mixed patterns (now resolved): - ~~JSONResponse for errors~~ → Removed (was unused import) - HTTPException (standard) → All errors now use this pattern consistently
10. Configuration Complexity¶
Status: ✅ Completed (v1.13.10) File: ppxai/config/ (~700 lines across 3 files)
Resolution: Split monolithic config.py into config/ package:
- config/store.py - Thread-safe ConfigStore singleton
- config/loader.py - Loading, validation, built-in providers
- config/__init__.py - Public API with 50+ functions
Key improvements:
- Clear separation of concerns (storage vs loading vs API)
- Thread-safe and asyncio-safe for multi-worker deployments
- Lazy loading via proxy classes (_ProvidersProxy, _ModelsProxy)
- Test-friendly with ConfigStore.set_for_testing() method
11. Abrupt Process Termination¶
Status: ✅ Completed (v1.13.10) File: ppxai/server/http.py
Resolution (v1.13.10):
- Replaced os._exit(0) with graceful shutdown via asyncio.Event
- Added _shutdown_event global for signaling shutdown
- Created _run_server_with_graceful_shutdown() helper using uvicorn.Server directly
- /shutdown endpoint now sets event instead of calling os._exit()
- Cleanup handlers (atexit) now run properly
- Lifespan shutdown hooks execute correctly
Low Priority¶
12. Legacy Backward Compatibility Code¶
Status: ✅ Addressed (v1.13.10) File: ppxai/commands/handler.py
Resolution: Added deprecation warning for legacy constructor signature:
warnings.warn(
"Passing client object to CommandHandler is deprecated. "
"Use CommandHandler(api_key, model, base_url, provider) instead. "
"Will be removed in v2.0.0.",
DeprecationWarning,
stacklevel=2
)
Next step: Remove legacy signature in v2.0.0.
13. Version Marker Comments¶
Status: Policy Defined Scope: Throughout codebase (~150+ markers)
Pattern: Code annotated with version numbers (v1.11.0, v1.12.0, v1.13.x) scattered as comments.
Impact: Maintenance burden, harder to track when compatibility code can be removed.
Policy (Agreed):
-
Remove informational markers - Feature annotations like
# v1.13.4: Tool usage trackingprovide no value; git history serves this purpose -
Keep only compatibility markers - Code that needs removal in a future version should use:
-
EOL dates - Compatibility code has 3-month EOL from introduction
Cleanup Schedule: - Cleanup happens at minor version releases - Example: When releasing v1.14.0, remove all v1.13.x informational markers - Compatibility markers remain until their stated EOL version
Files Most Affected:
- vscode-extension/src/chatPanel.ts (~45 markers)
- ppxai/engine/client.py (~20 markers)
- vscode-extension/src/httpClient.ts (~15 markers)
- ppxai/engine/session.py (~12 markers)
14. Magic String Literals¶
Status: ✅ Completed (v1.13.10) File: ppxai/constants.py
Resolution: Converted class-based constants to str, Enum with validation helpers:
- ProviderName, MessageRole, ConsentMode, ConsentResponse - Now proper enums
- SystemPromptMode, ShellRiskLevel, FileEncoding, CheckpointBackend - Now proper enums
- Added is_valid_*() helper functions for runtime validation
- Added generic is_valid_enum() and get_enum_values() helpers
- Kept ConfigKey, ToolSetting, Default, APIEndpoint as classes (dict keys/URLs/integers)
Benefits:
- Seamless string comparison (no .value needed due to str, Enum)
- IDE autocompletion and type safety
- Runtime validation via helper functions
- Works with Python 3.10+ (no StrEnum dependency)
15. TypeScript let vs const¶
Status: ✅ Verified Correct (v1.13.10) File: vscode-extension/src/chatPanel.ts
Analysis (v1.13.10): Reviewed all 46 let declarations in chatPanel.ts:
- All are legitimately reassigned (if/else branches, loops, async operations)
- Original line numbers were outdated/incorrect
- No changes needed - code is properly using let where variables are mutable
Original claim: "Lines 179, 317, 357, 481, 658, 659, 823, 1215, 1338, 1352-1353 should be const" Finding: All checked variables ARE reassigned after declaration.
16. Container Deployment Support¶
Status: ✅ Completed (v1.13.10) Scope: New files created
Resolution: Full containerized deployment support added: - Dockerfile - Multi-stage build with uv package manager - docker-compose.yaml - Local development setup - kubernetes/deployment.yaml - Deployment with health probes - kubernetes/service.yaml - ClusterIP service - kubernetes/ingress.yaml - Nginx ingress with SSE support
Health endpoints (added in v1.13.10):
- /health - Liveness probe (always returns 200)
- /ready - Readiness probe (checks session manager)
Files Created:
ppxai/
├── Dockerfile # Multi-stage build (Python 3.11-slim)
├── docker-compose.yaml # Local dev with volume mounts
└── kubernetes/
├── deployment.yaml # 1 replica, resource limits, probes
├── service.yaml # ClusterIP on port 80
└── ingress.yaml # Nginx with SSE proxy settings
Usage:
# Docker
docker compose up --build
# Kubernetes
kubectl create secret generic ppxai-secrets --from-literal=PERPLEXITY_API_KEY=xxx
kubectl apply -f kubernetes/
Completed Items¶
Items moved here after being addressed:
| Item | Description | Fixed In | Date |
|---|---|---|---|
| #1 | Global state management - SessionManager singleton with thread safety | v1.13.10 | 2026-01-14 |
| #2 | commands.py - Migrated to Command Factory pattern in commands/ package | v1.13.10 | 2026-01-16 |
| #3 | Silent error handling - Added selective logging to 22 instances | v1.13.10 | 2026-01-15 |
| #4 | Container tools code duplication - refactored to CLITool hierarchy | v1.13.10 | 2026-01-14 |
| #5 | Consent Manager duplication - Extracted BaseConsentManager class | v1.13.10 | 2026-01-15 |
| #6 | Import structure - Refactored commands.py to DAG imports, updated ARCHITECTURE.md | v1.13.10 | 2026-01-15 |
| #7 | eval() usage - Replaced with AST-based safe evaluation | v1.13.10 | 2026-01-15 |
| #10 | config.py complexity - Split into config/ package with ConfigStore pattern | v1.13.10 | 2026-01-16 |
| #9 | HTTP error handling - Standardized on HTTPException, removed unused JSONResponse | v1.13.10 | 2026-01-16 |
| #11 | Abrupt process termination - Graceful shutdown via asyncio.Event | v1.13.10 | 2026-01-16 |
| #15 | TypeScript let vs const - Verified all 46 uses are correct | v1.13.10 | 2026-01-16 |
| - | Magic strings - Created ppxai/constants.py with centralized constants | v1.13.10 | 2026-01-16 |
| - | BUILTIN_PROVIDERS removal - JSON config as single source of truth | v1.13.10 | 2026-01-16 |
| #8 | Type hints - Added TypeScript interfaces for consent requests | v1.13.10 | 2026-01-17 |
| #12 | Legacy compat - Added deprecation warning for CommandHandler | v1.13.10 | 2026-01-17 |
| #14 | Magic strings - Converted constants.py to str,Enum with validation helpers | v1.13.10 | 2026-01-17 |
| #16 | Container deployment - Dockerfile, docker-compose, K8s manifests | v1.13.10 | 2026-01-17 |
| #2 | client.py refactoring - 5 phases, 36% reduction (2,037→1,311 lines) | v1.13.10 | 2026-01-18 |
| - | chatPanel.ts Phases 2-4 - EventBus + State Machine architecture (1,658 lines handlers/) | v1.13.10 | 2026-01-18 |
Refactoring Priority Matrix¶
| Priority | Category | Effort | Impact |
|---|---|---|---|
| ~~Critical~~ | ~~Global state~~ | ~~High~~ | ✅ Done |
| ~~Critical~~ | ~~Monolithic files~~ | ~~High~~ | ✅ Done (all files refactored) |
| ~~Critical~~ | ~~Silent errors~~ | ~~Medium~~ | ✅ Done |
| ~~High~~ | ~~Container tools duplication~~ | ~~Medium~~ | ✅ Done |
| ~~High~~ | ~~Consent duplication~~ | ~~Medium~~ | ✅ Done |
| ~~High~~ | ~~Circular imports~~ | ~~Medium~~ | ✅ Documented |
| ~~High~~ | ~~eval() usage~~ | ~~Low~~ | ✅ Done |
| ~~Medium~~ | ~~Type hints~~ | ~~Medium~~ | ✅ Partial |
| ~~Medium~~ | ~~HTTP error handling~~ | ~~Medium~~ | ✅ Done |
| ~~Medium~~ | ~~Config complexity~~ | ~~Medium~~ | ✅ Done |
| ~~Low~~ | ~~Legacy compatibility~~ | ~~Low~~ | ✅ Done |
| ~~Low~~ | ~~Magic strings~~ | ~~Low~~ | ✅ Done (constants.py) |
Files Most in Need of Refactoring¶
- ~~
ppxai/server/http.py~~ - ✅ Done (SessionManager extracted) - ~~
ppxai/commands.py~~ - ✅ Done (Command Factory pattern incommands/package) - ~~
ppxai/config.py~~ - ✅ Done (Split intoconfig/package with ConfigStore) - ~~
ppxai/engine/client.py~~ - ✅ Done (5-phase refactoring, see DESIGN-CLIENT-REFACTOR.md) - ~~
ppxai/engine/tools/builtin/container.py~~ - ✅ Done (refactored to CLITool hierarchy) - ~~
vscode-extension/src/chatPanel.ts~~ - ✅ Done (Phases 1-4, EventBus + State Machine)
All critical monolithic files have been refactored. No major refactoring debt remains.
How to Use This Document¶
- Before starting work: Check if your area has known debt
- After fixing an item: Move it to "Completed Items" with version and date
- Found new debt: Add it with appropriate priority
- Review regularly: During planning, assess what can be addressed