refactor: implement in-process worker architecture for hooks (#722)
* fix: stop generating empty CLAUDE.md files - Return empty string instead of "No recent activity" when no observations exist - Skip writing CLAUDE.md files when formatted content is empty - Remove redundant "auto-generated by claude-mem" HTML comment - Clean up 98 existing empty CLAUDE.md files across the codebase - Update tests to expect empty string for empty input Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * build assets * refactor: implement in-process worker architecture for hooks Replaces spawn-based worker startup with in-process architecture: - Hook processes now become the worker when port 37777 is free - Eliminates Windows spawn issues (NO SPAWN rule) - SessionStart chains: smart-install && stop && context Key changes: - worker-service.ts: hook case starts WorkerService in-process - hook-command.ts: skipExit option prevents process.exit() when hosting worker - hooks.json: single chained command replaces separate start/hook commands - worker-utils.ts: ensureWorkerRunning() returns boolean, doesn't block - handlers: graceful fallback when worker unavailable All 761 tests pass. Manual verification confirms hook stays alive as worker. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * context * a * MAESTRO: Mark PR #722 test verification task complete All 797 tests passed (3 skipped, 0 failed) after merge conflict resolution. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * MAESTRO: Mark PR #722 build verification task complete * MAESTRO: Mark PR #722 code review task complete Code review verified: - worker-service.ts hook case starts WorkerService in-process - hook-command.ts has skipExit option - hooks.json uses single chained command - worker-utils.ts ensureWorkerRunning() returns boolean Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * MAESTRO: Mark PR #722 conflict resolution push task complete Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+17
-23
@@ -4,7 +4,6 @@ import { readFileSync } from "fs";
|
||||
import { logger } from "../utils/logger.js";
|
||||
import { HOOK_TIMEOUTS, getTimeout } from "./hook-constants.js";
|
||||
import { SettingsDefaultsManager } from "./SettingsDefaultsManager.js";
|
||||
import { getWorkerRestartInstructions } from "../utils/error-messages.js";
|
||||
|
||||
const MARKETPLACE_ROOT = path.join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack');
|
||||
|
||||
@@ -112,30 +111,25 @@ async function checkWorkerVersion(): Promise<void> {
|
||||
|
||||
/**
|
||||
* Ensure worker service is running
|
||||
* Polls until worker is ready (assumes worker-service.cjs start was called by hooks.json)
|
||||
* Quick health check - returns false if worker not healthy (doesn't block)
|
||||
* Port might be in use by another process, or worker might not be started yet
|
||||
*/
|
||||
export async function ensureWorkerRunning(): Promise<void> {
|
||||
const maxRetries = 75; // 15 seconds total
|
||||
const pollInterval = 200;
|
||||
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
try {
|
||||
if (await isWorkerHealthy()) {
|
||||
await checkWorkerVersion(); // logs warning on mismatch, doesn't restart
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
logger.debug('SYSTEM', 'Worker health check failed, will retry', {
|
||||
attempt: i + 1,
|
||||
maxRetries,
|
||||
error: e instanceof Error ? e.message : String(e)
|
||||
});
|
||||
export async function ensureWorkerRunning(): Promise<boolean> {
|
||||
// Quick health check (single attempt, no polling)
|
||||
try {
|
||||
if (await isWorkerHealthy()) {
|
||||
await checkWorkerVersion(); // logs warning on mismatch, doesn't restart
|
||||
return true; // Worker healthy
|
||||
}
|
||||
await new Promise(r => setTimeout(r, pollInterval));
|
||||
} catch (e) {
|
||||
// Not healthy - log for debugging
|
||||
logger.debug('SYSTEM', 'Worker health check failed', {
|
||||
error: e instanceof Error ? e.message : String(e)
|
||||
});
|
||||
}
|
||||
|
||||
throw new Error(getWorkerRestartInstructions({
|
||||
port: getWorkerPort(),
|
||||
customPrefix: 'Worker did not become ready within 15 seconds.'
|
||||
}));
|
||||
// Port might be in use by something else, or worker not started
|
||||
// Return false but don't throw - let caller decide how to handle
|
||||
logger.warn('SYSTEM', 'Worker not healthy, hook will proceed gracefully');
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user