05323c9db5
* refactor(worker): remove dead code from worker-service.ts Remove ~216 lines of unreachable code: - Delete `runInteractiveSetup` function (defined but never called) - Remove unused imports: fs namespace, spawn, homedir, readline, existsSync/writeFileSync/readFileSync/mkdirSync - Clean up CursorHooksInstaller imports (keep only used exports) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(worker): only enable SDK fallback when Claude is configured Add isConfigured() method to SDKAgent that checks for ANTHROPIC_API_KEY or claude CLI availability. Worker now only sets SDK agent as fallback for third-party providers when credentials exist, preventing cascading failures for users who intentionally use Gemini/OpenRouter without Claude. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(worker): remove misleading re-export indirection Remove unnecessary re-export of updateCursorContextForProject from worker-service.ts. ResponseProcessor now imports directly from CursorHooksInstaller.ts where the function is defined. This eliminates misleading indirection that suggested a circular dependency existed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(mcp): use build-time injected version instead of hardcoded strings Replace hardcoded '1.0.0' version strings with __DEFAULT_PACKAGE_VERSION__ constant that esbuild replaces at build time. This ensures MCP server and client versions stay synchronized with package.json. - worker-service.ts: MCP client version now uses packageVersion - ChromaSync.ts: MCP client version now uses packageVersion - mcp-server.ts: MCP server version now uses packageVersion - Added clarifying comments for empty MCP capabilities objects Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Implement cleanup and validation plans for worker-service.ts - Added a comprehensive cleanup plan addressing 23 identified issues in worker-service.ts, focusing on safe deletions, low-risk simplifications, and medium-risk improvements. - Created an execution plan for validating intentional patterns in worker-service.ts, detailing necessary actions and priorities. - Generated a report on unjustified logic in worker-service.ts, categorizing issues by severity and providing recommendations for immediate and short-term actions. - Introduced documentation for recent activity in the mem-search plugin, enhancing traceability and context for changes. * fix(sdk): remove dangerous ANTHROPIC_API_KEY check from isConfigured Claude Code uses CLI authentication, not direct API calls. Checking for ANTHROPIC_API_KEY could accidentally use a user's API key (from other projects) which costs 20x more than Claude Code's pricing. Now only checks for claude CLI availability. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(worker): remove fallback agent concept entirely Users who choose Gemini/OpenRouter want those providers, not secret fallback behavior. Removed setFallbackAgent calls and the unused isConfigured() method. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
337 lines
9.0 KiB
Markdown
337 lines
9.0 KiB
Markdown
# Intentional Patterns Validation Report
|
|
|
|
**Generated:** 2026-01-13
|
|
**Purpose:** Validate whether "intentional" patterns in worker-service.ts are truly justified
|
|
|
|
---
|
|
|
|
## Summary Table
|
|
|
|
| Pattern | Verdict | Evidence Quality | Recommendation |
|
|
|---------|---------|------------------|----------------|
|
|
| Exit code 0 always | **JUSTIFIED** | HIGH | Keep (well documented) |
|
|
| Circular import re-export | **UNNECESSARY** | HIGH | Remove (no actual circular dep) |
|
|
| Fallback agent without check | **OVERSIGHT** | HIGH | Fix (real bug risk) |
|
|
| MCP version hardcoded | **COSMETIC** | MEDIUM | Update to match package.json |
|
|
| Empty MCP capabilities | **INTENTIONAL** | LOW | Add documentation comment |
|
|
| `as Error` casts | **JUSTIFIED** | HIGH | Keep (documented policy) |
|
|
|
|
---
|
|
|
|
## Pattern 1: Exit Code 0 Always
|
|
|
|
### Evidence
|
|
|
|
| Category | Details |
|
|
|----------|---------|
|
|
| **Locations** | 8 explicit `process.exit(0)` calls in worker-service.ts |
|
|
| **Documentation** | CLAUDE.md lines 44-54, CHANGELOG v9.0.2 |
|
|
| **Git History** | Commit 222a73da (Jan 8, 2026) - detailed explanation |
|
|
| **Tests** | 23 passing tests in `worker-json-status.test.ts` |
|
|
| **Comments** | 5 detailed comments at each exit point |
|
|
|
|
### Justification
|
|
|
|
```markdown
|
|
## Exit Code Strategy (from CLAUDE.md)
|
|
|
|
- **Exit 0**: Success or graceful shutdown (Windows Terminal closes tabs)
|
|
- **Exit 1**: Non-blocking error (stderr shown to user, continues)
|
|
- **Exit 2**: Blocking error (stderr fed to Claude for processing)
|
|
|
|
**Philosophy**: Worker/hook errors exit with code 0 to prevent Windows Terminal
|
|
tab accumulation. The wrapper/plugin layer handles restart logic.
|
|
```
|
|
|
|
### Commit Evidence
|
|
|
|
```
|
|
commit 222a73da5dc875e666c3dd2c96c9d178dd7b884d
|
|
Date: Thu Jan 8 15:02:56 2026 -0500
|
|
|
|
fix: graceful exit strategy to prevent Windows Terminal tab accumulation (#625)
|
|
|
|
Problem:
|
|
Windows Terminal keeps tabs open when processes exit with code 1, leading
|
|
to tab accumulation during worker lifecycle operations.
|
|
|
|
Solution:
|
|
Implemented graceful exit strategy using exit code 0 for all expected failure
|
|
scenarios. The wrapper and plugin handle restart logic.
|
|
```
|
|
|
|
### Verdict: **JUSTIFIED**
|
|
|
|
- Real Windows Terminal behavior documented
|
|
- Comprehensive test coverage validating pattern
|
|
- Consistent implementation across all exit points
|
|
- Error status communicated via JSON, not exit code
|
|
|
|
### Risk
|
|
|
|
- Breaks Unix convention but trades correctness for UX
|
|
- Shell scripts calling worker commands won't detect errors via `$?`
|
|
- Mitigated by JSON status output for programmatic consumers
|
|
|
|
---
|
|
|
|
## Pattern 2: Circular Import Re-Export
|
|
|
|
### The Code (worker-service.ts:77-78)
|
|
|
|
```typescript
|
|
// Re-export updateCursorContextForProject for SDK agents
|
|
export { updateCursorContextForProject };
|
|
```
|
|
|
|
### Import Chain Analyzed
|
|
|
|
```
|
|
CursorHooksInstaller.ts (defines function)
|
|
↓
|
|
worker-service.ts (imports, re-exports)
|
|
↓
|
|
ResponseProcessor.ts (imports from worker-service.ts)
|
|
```
|
|
|
|
### Actual Circular Dependency: **NONE EXISTS**
|
|
|
|
```
|
|
CursorHooksInstaller.ts → imports nothing from worker-service.ts ✓
|
|
ResponseProcessor.ts → only imports the re-exported function ✓
|
|
```
|
|
|
|
ResponseProcessor.ts **could** import directly:
|
|
|
|
```typescript
|
|
// Current (via re-export):
|
|
import { updateCursorContextForProject } from '../../worker-service.js';
|
|
|
|
// Alternative (direct - would work fine):
|
|
import { updateCursorContextForProject } from '../../integrations/CursorHooksInstaller.js';
|
|
```
|
|
|
|
### Verdict: **UNNECESSARY**
|
|
|
|
- Comment claims "avoids circular imports" but no circular dependency exists
|
|
- Likely a precaution during refactoring that became stale
|
|
- Harmless but misleading
|
|
|
|
### Recommendation
|
|
|
|
- **Option A**: Remove re-export, update ResponseProcessor.ts import path
|
|
- **Option B**: Update comment to explain actual reason (e.g., "API surface simplification")
|
|
|
|
---
|
|
|
|
## Pattern 3: Fallback Agent Without Verification
|
|
|
|
### The Code (worker-service.ts:144-146)
|
|
|
|
```typescript
|
|
this.geminiAgent.setFallbackAgent(this.sdkAgent);
|
|
this.openRouterAgent.setFallbackAgent(this.sdkAgent);
|
|
```
|
|
|
|
### Fallback Trigger Logic
|
|
|
|
```typescript
|
|
// GeminiAgent.ts:284-294
|
|
if (shouldFallbackToClaude(error) && this.fallbackAgent) {
|
|
logger.warn('SDK', 'Gemini API failed, falling back to Claude SDK', {...});
|
|
return this.fallbackAgent.startSession(session, worker);
|
|
}
|
|
```
|
|
|
|
### Problem Scenario
|
|
|
|
1. User chooses Gemini because they **don't have Claude credentials**
|
|
2. Gemini encounters transient error (429 rate limit, 503 server error)
|
|
3. Code attempts fallback to Claude SDK
|
|
4. Claude SDK fails (no credentials) → **cascading failure**
|
|
5. User sees cryptic error, session lost
|
|
|
|
### What's Checked vs What's NOT
|
|
|
|
| Check | Implemented |
|
|
|-------|-------------|
|
|
| `this.fallbackAgent` is not null | ✅ Yes |
|
|
| Fallback agent initialized successfully | ❌ No |
|
|
| Fallback agent has valid credentials | ❌ No |
|
|
| Fallback agent can make API calls | ❌ No |
|
|
|
|
### Verdict: **OVERSIGHT - Real Bug Risk**
|
|
|
|
- Documentation claims "seamless fallback"
|
|
- No health check verifies fallback is functional
|
|
- Users without Claude credentials face silent failure mode
|
|
|
|
### Recommendation
|
|
|
|
Add verification at initialization:
|
|
|
|
```typescript
|
|
// Option 1: Verify fallback can initialize
|
|
if (this.sdkAgent.isConfigured()) {
|
|
this.geminiAgent.setFallbackAgent(this.sdkAgent);
|
|
}
|
|
|
|
// Option 2: Log warning when fallback unavailable
|
|
if (!this.sdkAgent.isConfigured()) {
|
|
logger.warn('WORKER', 'Claude SDK not configured - Gemini fallback disabled');
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Pattern 4: Hardcoded MCP Version "1.0.0"
|
|
|
|
### Locations (3 instances)
|
|
|
|
| File | Line | Version |
|
|
|------|------|---------|
|
|
| worker-service.ts | 157-160 | `1.0.0` |
|
|
| ChromaSync.ts | 126-131 | `1.0.0` |
|
|
| mcp-server.ts | 236-245 | `1.0.0` |
|
|
|
|
### Version Mismatch
|
|
|
|
| Source | Version |
|
|
|--------|---------|
|
|
| package.json | `9.0.4` |
|
|
| MCP SDK | `1.25.1` |
|
|
| MCP Client/Server instances | `1.0.0` |
|
|
|
|
### Does It Matter?
|
|
|
|
**Investigation found:**
|
|
- MCP servers do NOT validate client version
|
|
- Connections succeed regardless of version value
|
|
- Version appears to be for logging/debugging only (like HTTP User-Agent)
|
|
|
|
### Verdict: **COSMETIC - Low Priority**
|
|
|
|
- Functionally doesn't matter
|
|
- Inconsistent with package version is confusing
|
|
- Should be updated for cleanliness
|
|
|
|
### Recommendation
|
|
|
|
```typescript
|
|
// Update to use package version
|
|
import { version } from '../../package.json' assert { type: 'json' };
|
|
|
|
this.mcpClient = new Client({
|
|
name: 'worker-search-proxy',
|
|
version: version // Use actual package version
|
|
}, { capabilities: {} });
|
|
```
|
|
|
|
---
|
|
|
|
## Pattern 5: Empty MCP Capabilities
|
|
|
|
### The Code
|
|
|
|
```typescript
|
|
{ capabilities: {} } // All 3 MCP client instances
|
|
```
|
|
|
|
### Investigation
|
|
|
|
- MCP specification: **Servers** declare capabilities (tools, resources, prompts)
|
|
- MCP specification: **Clients** don't typically declare capabilities
|
|
- No validation found in any MCP server
|
|
- Pattern works correctly
|
|
|
|
### Verdict: **INTENTIONAL - Documentation Gap**
|
|
|
|
- Empty capabilities is likely correct for clients
|
|
- MCP SDK documentation doesn't clarify this
|
|
- Works fine in practice
|
|
|
|
### Recommendation
|
|
|
|
Add clarifying comment:
|
|
|
|
```typescript
|
|
// MCP spec: Clients accept all server capabilities; no declaration needed
|
|
{ capabilities: {} }
|
|
```
|
|
|
|
---
|
|
|
|
## Pattern 6: `as Error` Casts
|
|
|
|
### Locations (8 in worker-service.ts)
|
|
|
|
Lines: 236, 314, 317, 339, 393, 469, 636, 796
|
|
|
|
### Why It's Used
|
|
|
|
TypeScript 4.0+ catch clauses have `unknown` type:
|
|
|
|
```typescript
|
|
try {
|
|
// ...
|
|
} catch (error) { // error: unknown (not Error)
|
|
logger.error('X', 'msg', {}, error as Error); // Cast needed for logger
|
|
}
|
|
```
|
|
|
|
### Project Documentation
|
|
|
|
**File:** `scripts/anti-pattern-test/CLAUDE.md`
|
|
|
|
Establishes explicit error handling policy with:
|
|
- 5 questions before writing try-catch
|
|
- Forbidden patterns list
|
|
- Anti-pattern detection script
|
|
- Critical paths protection
|
|
|
|
### Anti-Pattern Detection
|
|
|
|
```bash
|
|
bun run scripts/anti-pattern-test/detect-error-handling-antipatterns.ts
|
|
```
|
|
|
|
Scans for 7 anti-patterns including:
|
|
- Empty catch blocks
|
|
- Catch without logging
|
|
- Generic error handling
|
|
|
|
### Verdict: **JUSTIFIED - Documented Policy**
|
|
|
|
- Explicit project convention with tooling support
|
|
- Alternative (type guards) would add verbosity
|
|
- Logger requires Error type for stack trace
|
|
- Pre-commit validation enforces consistency
|
|
|
|
---
|
|
|
|
## Action Items Summary
|
|
|
|
| Pattern | Action | Priority |
|
|
|---------|--------|----------|
|
|
| Exit code 0 | Keep as-is | N/A |
|
|
| Circular import re-export | Remove or fix comment | LOW |
|
|
| Fallback agent | **Add availability check** | **HIGH** |
|
|
| MCP version | Update to package.json version | LOW |
|
|
| Empty capabilities | Add documentation comment | LOW |
|
|
| `as Error` casts | Keep as-is | N/A |
|
|
|
|
---
|
|
|
|
## Questions for Your Validation
|
|
|
|
1. **Exit code 0**: Is the Windows Terminal workaround acceptable, or should we exit non-zero and document that users need to parse JSON status?
|
|
|
|
2. **Circular import**: Should we remove the re-export (cleaner) or update the comment to reflect the real reason?
|
|
|
|
3. **Fallback agent**: Should we:
|
|
- A) Add initialization-time verification
|
|
- B) Document the limitation and keep as-is
|
|
- C) Allow users to disable fallback behavior
|
|
|
|
4. **MCP version**: Worth updating all 3 instances, or leave as cosmetic debt?
|