fix: Resolve signal.json path mismatch for standalone agents
Standalone agents (no initiative or 0 linked projects) run in a workspace/ subdirectory, but signal.json lookups used the parent directory. This caused all standalone agents to be marked "crashed" despite successful completion. Track the actual agent cwd at spawn time via ActiveAgent.agentCwd and probe for the workspace/ subdirectory during reconciliation and crash detection paths.
This commit is contained in:
@@ -39,7 +39,7 @@ import { writeInputFiles } from './file-io.js';
|
||||
import { buildWorkspaceLayout, buildInterAgentCommunication } from './prompts/index.js';
|
||||
import { getProvider } from './providers/registry.js';
|
||||
import { createModuleLogger } from '../logger/index.js';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { join } from 'node:path';
|
||||
import { unlink, readFile } from 'node:fs/promises';
|
||||
import { existsSync, writeFileSync } from 'node:fs';
|
||||
import type { AccountCredentialManager } from './credentials/types.js';
|
||||
@@ -340,7 +340,7 @@ export class MultiProviderAgentManager implements AgentManager {
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
const activeEntry: ActiveAgent = { agentId, pid, tailer, outputFilePath };
|
||||
const activeEntry: ActiveAgent = { agentId, pid, tailer, outputFilePath, agentCwd: finalCwd };
|
||||
this.activeAgents.set(agentId, activeEntry);
|
||||
log.info({ agentId, alias, pid, diagnosticWritten: true }, 'detached subprocess started with diagnostic');
|
||||
|
||||
@@ -820,7 +820,7 @@ export class MultiProviderAgentManager implements AgentManager {
|
||||
|
||||
// Check if the agent has output that indicates successful completion
|
||||
if (agent.outputFilePath) {
|
||||
const hasCompletion = await this.checkAgentCompletionResult(agent.outputFilePath);
|
||||
const hasCompletion = await this.checkAgentCompletionResult(agent.worktreeId);
|
||||
if (hasCompletion) {
|
||||
log.info({
|
||||
agentId: processId,
|
||||
@@ -872,14 +872,21 @@ export class MultiProviderAgentManager implements AgentManager {
|
||||
|
||||
/**
|
||||
* Check if agent completed successfully by reading signal.json file.
|
||||
* Probes the workspace/ subdirectory for standalone agents.
|
||||
*/
|
||||
private async checkAgentCompletionResult(outputFilePath: string): Promise<boolean> {
|
||||
private async checkAgentCompletionResult(worktreeId: string): Promise<boolean> {
|
||||
try {
|
||||
const agentDir = dirname(outputFilePath);
|
||||
const signalPath = join(agentDir, '.cw/output/signal.json');
|
||||
// Resolve actual agent workdir — standalone agents have .cw inside workspace/ subdir
|
||||
let agentWorkdir = this.processManager.getAgentWorkdir(worktreeId);
|
||||
const workspaceSub = join(agentWorkdir, 'workspace');
|
||||
if (!existsSync(join(agentWorkdir, '.cw', 'output')) && existsSync(join(workspaceSub, '.cw'))) {
|
||||
agentWorkdir = workspaceSub;
|
||||
}
|
||||
|
||||
const signalPath = join(agentWorkdir, '.cw/output/signal.json');
|
||||
|
||||
if (!existsSync(signalPath)) {
|
||||
log.debug({ outputFilePath, signalPath }, 'no signal.json found - agent not completed');
|
||||
log.debug({ worktreeId, signalPath }, 'no signal.json found - agent not completed');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -890,15 +897,15 @@ export class MultiProviderAgentManager implements AgentManager {
|
||||
const completed = signal.status === 'done' || signal.status === 'questions' || signal.status === 'error';
|
||||
|
||||
if (completed) {
|
||||
log.debug({ outputFilePath, signal }, 'agent completion detected via signal.json');
|
||||
log.debug({ worktreeId, signal }, 'agent completion detected via signal.json');
|
||||
} else {
|
||||
log.debug({ outputFilePath, signal }, 'signal.json found but status indicates incomplete');
|
||||
log.debug({ worktreeId, signal }, 'signal.json found but status indicates incomplete');
|
||||
}
|
||||
|
||||
return completed;
|
||||
|
||||
} catch (err) {
|
||||
log.warn({ outputFilePath, err: err instanceof Error ? err.message : String(err) }, 'failed to read or parse signal.json');
|
||||
log.warn({ worktreeId, err: err instanceof Error ? err.message : String(err) }, 'failed to read or parse signal.json');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user