fix: allow notify reactions when auto is false, clean up reserved IDs on spawn failure
- Reactions with action: "notify" bypass the auto: false gate so merge-ready notifications fire for approved-and-green config - All spawn failure paths now delete the reserved session metadata file Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
65787f08e3
commit
07b3a553f7
|
|
@ -418,8 +418,11 @@ export function createLifecycleManager(deps: LifecycleManagerDeps): LifecycleMan
|
||||||
? { ...globalReaction, ...projectReaction }
|
? { ...globalReaction, ...projectReaction }
|
||||||
: globalReaction;
|
: globalReaction;
|
||||||
|
|
||||||
if (reactionConfig && reactionConfig.auto !== false && reactionConfig.action) {
|
if (reactionConfig && reactionConfig.action) {
|
||||||
await executeReaction(event, reactionKey, reactionConfig as ReactionConfig);
|
// auto: false skips automated agent actions but still allows notifications
|
||||||
|
if (reactionConfig.auto !== false || reactionConfig.action === "notify") {
|
||||||
|
await executeReaction(event, reactionKey, reactionConfig as ReactionConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -467,8 +470,10 @@ export function createLifecycleManager(deps: LifecycleManagerDeps): LifecycleMan
|
||||||
const reactionKey = eventToReactionKey("summary.all_complete");
|
const reactionKey = eventToReactionKey("summary.all_complete");
|
||||||
if (reactionKey) {
|
if (reactionKey) {
|
||||||
const reactionConfig = config.reactions[reactionKey];
|
const reactionConfig = config.reactions[reactionKey];
|
||||||
if (reactionConfig && reactionConfig.auto !== false && reactionConfig.action) {
|
if (reactionConfig && reactionConfig.action) {
|
||||||
await executeReaction(event, reactionKey, reactionConfig as ReactionConfig);
|
if (reactionConfig.auto !== false || reactionConfig.action === "notify") {
|
||||||
|
await executeReaction(event, reactionKey, reactionConfig as ReactionConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -192,28 +192,38 @@ export function createSessionManager(deps: SessionManagerDeps): SessionManager {
|
||||||
// Create workspace (if workspace plugin is available)
|
// Create workspace (if workspace plugin is available)
|
||||||
let workspacePath = project.path;
|
let workspacePath = project.path;
|
||||||
if (plugins.workspace) {
|
if (plugins.workspace) {
|
||||||
const wsInfo = await plugins.workspace.create({
|
try {
|
||||||
projectId: spawnConfig.projectId,
|
const wsInfo = await plugins.workspace.create({
|
||||||
project,
|
projectId: spawnConfig.projectId,
|
||||||
sessionId,
|
project,
|
||||||
branch,
|
sessionId,
|
||||||
});
|
branch,
|
||||||
workspacePath = wsInfo.path;
|
});
|
||||||
|
workspacePath = wsInfo.path;
|
||||||
|
|
||||||
// Run post-create hooks — clean up workspace on failure (skip if project root)
|
// Run post-create hooks — clean up workspace on failure
|
||||||
if (plugins.workspace.postCreate) {
|
if (plugins.workspace.postCreate) {
|
||||||
try {
|
try {
|
||||||
await plugins.workspace.postCreate(wsInfo, project);
|
await plugins.workspace.postCreate(wsInfo, project);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (workspacePath !== project.path) {
|
if (workspacePath !== project.path) {
|
||||||
try {
|
try {
|
||||||
await plugins.workspace.destroy(workspacePath);
|
await plugins.workspace.destroy(workspacePath);
|
||||||
} catch {
|
} catch {
|
||||||
/* best effort */
|
/* best effort */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Clean up reserved session ID on workspace failure
|
||||||
|
try {
|
||||||
|
deleteMetadata(config.dataDir, sessionId, false);
|
||||||
|
} catch {
|
||||||
|
/* best effort */
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +252,7 @@ export function createSessionManager(deps: SessionManagerDeps): SessionManager {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Clean up workspace if agent config or runtime creation failed
|
// Clean up workspace and reserved ID if agent config or runtime creation failed
|
||||||
if (plugins.workspace && workspacePath !== project.path) {
|
if (plugins.workspace && workspacePath !== project.path) {
|
||||||
try {
|
try {
|
||||||
await plugins.workspace.destroy(workspacePath);
|
await plugins.workspace.destroy(workspacePath);
|
||||||
|
|
@ -250,6 +260,11 @@ export function createSessionManager(deps: SessionManagerDeps): SessionManager {
|
||||||
/* best effort */
|
/* best effort */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
deleteMetadata(config.dataDir, sessionId, false);
|
||||||
|
} catch {
|
||||||
|
/* best effort */
|
||||||
|
}
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue