* 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>
12 KiB
Unjustified Logic Report - worker-service.ts
Generated: 2026-01-13
Source: src/services/worker-service.ts (1445 lines)
Status: Pending Review
Summary
23 items identified lacking clear justification. Categorized by severity.
HIGH SEVERITY
1. Dead Function: runInteractiveSetup (~275 lines)
Location: Lines 837-1111
async function runInteractiveSetup(): Promise<number> {
// ~275 lines of interactive wizard code
}
What it does: Interactive CLI wizard for Cursor setup.
Why it's questionable: Function is defined but never called anywhere. Grep shows only the definition. The main() switch handles 'cursor' via handleCursorCommand, not this function.
Justification status: No justification found. Appears to be dead code from refactoring.
MEDIUM SEVERITY
2. 5-Minute Initialization Timeout
Location: Lines 464-478
const timeoutMs = 300000; // 5 minutes
await Promise.race([this.initializationComplete, timeoutPromise]);
What it does: Blocks /api/context/inject for up to 5 minutes.
Why it's questionable: HTTP request hanging for 5 minutes is extreme.
Justification status: "5 minutes seems excessive but matches MCP init timeout for consistency" - circular reasoning.
3. Redundant Signal Handler Synchronization
Location: Lines 412-434
const shutdownRef = { value: this.isShuttingDown };
const handler = createSignalHandler(() => this.shutdown(), shutdownRef);
process.on('SIGTERM', () => {
this.isShuttingDown = shutdownRef.value;
handler('SIGTERM');
});
What it does: Creates reference object, passes to handler, copies value back.
Why it's questionable: Overly complex. this.isShuttingDown could be used directly via closure.
Justification status: "Signal handler needs mutable reference" - but closure would work.
4. Dual Initialization Tracking (Promise + Flag)
Location: Lines 322-326, 633-634
private initializationComplete: Promise<void>;
private initializationCompleteFlag: boolean = false;
What it does: Maintains both Promise and boolean for same state.
Why it's questionable: Two sources of truth. Promise could resolve to boolean, or sync code could use a different pattern.
Justification status: Comments explain separately but not why both needed.
5. Over-Commenting (~40% of file)
Location: Throughout
// WHAT: Imports centralized logging utility with structured output
// WHY: All worker logs go through this for consistent formatting
import { logger } from '../utils/logger.js';
What it does: WHAT/WHY comments on nearly every line.
Why it's questionable: Many describe obvious code. Creates visual noise. import { logger } is self-explanatory.
Justification status: No justification for this density.
6. Exit Code 0 Always (Even on Errors)
Location: Lines 1142, 1272-1287, 1417-1420
function exitWithStatus(status: 'ready' | 'error', message?: string): never {
console.log(JSON.stringify(output));
process.exit(0); // Always 0, even on error
}
What it does: Exits 0 regardless of success/failure.
Why it's questionable: Breaks Unix convention. Hides failures from scripts/monitoring.
Justification status: "Windows Terminal keeps tabs open on non-zero exit" - trades correctness for UI convenience.
7. Fallback Agent Without Verification
Location: Lines 357-363
this.geminiAgent.setFallbackAgent(this.sdkAgent);
this.openRouterAgent.setFallbackAgent(this.sdkAgent);
What it does: Sets Claude SDK as fallback for alternative providers.
Why it's questionable: User may choose Gemini because they DON'T have Claude subscription. Fallback would fail.
Justification status: "If Gemini fails, falls back to Claude SDK (if available)" - doesn't verify availability.
8. Re-Export to Avoid Circular Import
Location: Line 191
export { updateCursorContextForProject };
What it does: Re-exports imported function.
Why it's questionable: Creates odd import path. Masks architectural issue (circular dependency).
Justification status: "Avoids circular imports" - acknowledges architecture problem.
LOW SEVERITY
9. Unused Import: import * as fs
Location: Line 22
import * as fs from 'fs';
What it does: Imports fs namespace.
Why it's questionable: Namespace never used. Only specific named imports (line 34) are used.
Justification status: Comment claims "Used for file operations" - false.
10. Unused Import: spawn
Location: Line 26
import { spawn } from 'child_process';
What it does: Imports spawn function.
Why it's questionable: Never used. MCP spawning uses StdioClientTransport internally.
Justification status: Comment claims "Worker spawns MCP server" - misleading.
11. onRestart = onShutdown (Identical Callbacks)
Location: Lines 395-396
onShutdown: () => this.shutdown(),
onRestart: () => this.shutdown()
What it does: Both callbacks do the exact same thing.
Why it's questionable: Naming implies different behavior.
Justification status: No justification for why restart just calls shutdown.
12. 100ms Magic Number in Recovery Loop
Location: Line 767
await new Promise(resolve => setTimeout(resolve, 100));
What it does: 100ms delay between session recovery.
Why it's questionable: Why 100ms specifically? Not 50ms or 200ms?
Justification status: "Prevents thundering herd" - purpose explained, value unexplained.
13. Dynamic Import Already Loaded
Location: Lines 709-710
const { PendingMessageStore } = await import('./sqlite/PendingMessageStore.js');
What it does: Dynamic import in processPendingQueues.
Why it's questionable: Same import in initializeBackground (line 558). Already loaded by auto-recovery call.
Justification status: "Lazy load because method may not be called often" - misleading, always called at startup.
14. Defensive Null Check for Race Condition
Location: Lines 663-669
if (!session) return;
What it does: Early returns if session null.
Why it's questionable: Comment admits "Session could be deleted between queue check and processor start" - hints at design issue.
Justification status: Justified, but suggests architecture problem.
15. Eager Broadcaster Init (Before Server)
Location: Lines 347-349
this.sseBroadcaster = new SSEBroadcaster();
What it does: Creates broadcaster in constructor.
Why it's questionable: Comment says "SSE clients can connect before background init" - but server not started yet.
Justification status: Comment is technically incorrect.
16. Hardcoded MCP Version
Location: Lines 385-388
this.mcpClient = new Client({
name: 'worker-search-proxy',
version: '1.0.0' // Hardcoded, doesn't match package.json
}, { capabilities: {} });
What it does: Hardcodes version to 1.0.0.
Why it's questionable: Doesn't match actual package version.
Justification status: No justification for specific version.
17. Nullable SearchRoutes After Init Complete
Location: Lines 314, 479-484
private searchRoutes: SearchRoutes | null = null;
// After awaiting initializationComplete:
if (!this.searchRoutes) {
res.status(503).json({ error: 'Search routes not initialized' });
}
What it does: Null check after init should be complete.
Why it's questionable: If init succeeded, should never be null.
Justification status: Explains async nature, not why remains nullable after.
18. Complex ESM/CJS Module Detection
Location: Lines 1433-1439
const isMainModule = typeof require !== 'undefined' && typeof module !== 'undefined'
? require.main === module || !module.parent
: import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith('worker-service');
What it does: Complex conditional for both module systems.
Why it's questionable: File is ESM-only (uses import). CJS checks unnecessary.
Justification status: "Works with both ESM and CommonJS" - but file is ESM-only.
19. Self-Questioning Comment
Location: Line 466
// REASON: 5 minutes seems excessive but matches MCP init timeout for consistency
What it does: Comment admits code is questionable.
Why it's questionable: If author thought excessive when writing, deserves investigation.
Justification status: Self-acknowledged as questionable.
20. homedir Import (Only Used in Dead Code)
Location: Line 30
import { homedir } from 'os';
What it does: Imports homedir.
Why it's questionable: Only used in runInteractiveSetup (dead code).
Justification status: Unused if dead code removed.
21. Unused Default Parameter
Location: Line 702
async processPendingQueues(sessionLimit: number = 10)
What it does: Default of 10.
Why it's questionable: Only call uses 50 (line 639). Default never used.
Justification status: No justification for 10 vs actual usage of 50.
22. Empty Capabilities Object
Location: Line 388
}, { capabilities: {} });
What it does: Passes empty capabilities to MCP client.
Why it's questionable: No explanation of what capabilities exist or why none needed.
Justification status: No justification found.
23. Unsafe as Error Casts
Location: Multiple (lines 513, 651, 771, etc.)
}, error as Error);
What it does: Casts unknown to Error.
Why it's questionable: Caught value might not be Error.
Justification status: Common TypeScript pattern, acceptable but potentially unsafe.
Quick Reference Table
| # | Issue | Severity | Action |
|---|---|---|---|
| 1 | Dead runInteractiveSetup (~275 lines) |
HIGH | Delete |
| 2 | 5-minute timeout | MEDIUM | Reduce to 30s |
| 3 | Redundant signal sync | MEDIUM | Simplify |
| 4 | Dual init tracking | MEDIUM | Unify |
| 5 | Over-commenting | MEDIUM | Reduce |
| 6 | Exit 0 always | MEDIUM | Reconsider |
| 7 | Fallback without check | MEDIUM | Verify availability |
| 8 | Re-export for circular | MEDIUM | Fix architecture |
| 9 | Unused fs namespace |
LOW | Delete |
| 10 | Unused spawn |
LOW | Delete |
| 11 | Identical callbacks | LOW | Clarify/merge |
| 12 | 100ms magic number | LOW | Document or configure |
| 13 | Redundant dynamic import | LOW | Remove |
| 14 | Defensive null (design smell) | LOW | Review architecture |
| 15 | Early broadcaster init | LOW | Fix comment |
| 16 | Hardcoded MCP version | LOW | Use package.json |
| 17 | Nullable after init | LOW | Clarify lifecycle |
| 18 | CJS checks in ESM | LOW | Remove |
| 19 | Self-questioning comment | LOW | Investigate |
| 20 | homedir in dead code |
LOW | Delete with dead code |
| 21 | Unused default param | LOW | Remove or document |
| 22 | Empty capabilities | LOW | Document |
| 23 | Unsafe error casts | LOW | Add type guards |
Recommendations
- Immediate: Delete dead
runInteractiveSetupfunction (275 lines, ~19% of file) - Immediate: Remove unused imports (
fsnamespace,spawn) - Short-term: Reduce 5-minute timeout to 30 seconds
- Short-term: Simplify signal handler pattern
- Consider: Reduce comment density to improve readability