mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
fix: install Codeman hooks into every claude workspace, not just cases Codeman created
A session in a linked case (or any pre-existing repo) ran with no hooks block at all: writeHooksConfig only fires when Codeman CREATES the case directory, and refreshStaleCodemanHooks deliberately never adds one. Every hook-driven surface was therefore dead in exactly the place most sessions run: no tab alert or phone-overview NEEDS YOU row when a dialog blocks the pane, no Approvals Inbox item, no push, no definitive stop/idle_prompt for respawn, and no stop/blocked for the agent wait endpoints. Both session-create paths and restoreMuxSessions() now call ensureCodemanHooks(), an add-only merge that keeps a user's own handlers and leaves a malformed settings file untouched. Claude Code re-reads settings.local.json, so a session already running in the workspace starts firing hooks without a restart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -76,6 +76,7 @@ import { RunSummaryTracker } from '../run-summary.js';
|
||||
import { PlanOrchestrator } from '../plan-orchestrator.js';
|
||||
import { OrchestratorLoop } from '../orchestrator-loop.js';
|
||||
import { getLifecycleLog } from '../session-lifecycle-log.js';
|
||||
import { ensureCodemanHooks } from '../hooks-config.js';
|
||||
import { PushSubscriptionStore } from '../push-store.js';
|
||||
import webpush from 'web-push';
|
||||
import { SseStreamManager } from './sse-stream-manager.js';
|
||||
@@ -2819,6 +2820,13 @@ export class WebServer extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
// Sessions recovered from a previous run predate the create-path hook
|
||||
// install, and these are long-lived: by the time a server restart comes
|
||||
// round a session may be days old and has been running hook-blind the
|
||||
// whole time. Claude Code re-reads settings.local.json, so writing the
|
||||
// block now arms the RUNNING CLI, no session restart needed.
|
||||
await this.ensureHooksForRecoveredWorkspaces();
|
||||
|
||||
// Start stats collection for mux sessions
|
||||
this.mux.startStatsCollection(STATS_COLLECTION_INTERVAL_MS);
|
||||
}
|
||||
@@ -2845,6 +2853,32 @@ export class WebServer extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Codeman's hooks into the workspaces of the sessions just recovered.
|
||||
*
|
||||
* Deduped by workspace, because sessions in one repo share a single
|
||||
* `.claude/settings.local.json` and the write is otherwise repeated per tab.
|
||||
* Claude mode only (nothing else reads `.claude` hooks), never for remote
|
||||
* sessions (their `workingDir` is a path on ANOTHER host, so writing it here
|
||||
* would scaffold a stray directory locally), and never for a docker case that
|
||||
* opted out of hooks.
|
||||
*
|
||||
* Failures are swallowed per workspace: `ensureCodemanHooks` already refuses
|
||||
* unsafe targets with a warning, and a workspace we cannot write to must not
|
||||
* stop the rest of recovery.
|
||||
*/
|
||||
private async ensureHooksForRecoveredWorkspaces(): Promise<void> {
|
||||
const workspaces = new Set<string>();
|
||||
for (const session of this.sessions.values()) {
|
||||
if (session.mode !== 'claude' || session.remote) continue;
|
||||
if (session.docker && !session.docker.hooksEnabled) continue;
|
||||
if (session.workingDir) workspaces.add(session.workingDir);
|
||||
}
|
||||
for (const workspace of workspaces) {
|
||||
await ensureCodemanHooks(workspace).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* COD-108 — handle a `remoteSessionDropped` emit from the watcher: reattach
|
||||
* the dropped remote session and report the outcome back to the watcher so it
|
||||
|
||||
Reference in New Issue
Block a user