feat(KB-150): kill active agent sessions on global pause
- Add settings:updated event to TaskStore with previous/new settings payload - Kill all active executor agent sessions when globalPause transitions false→true - Kill all active triage specification sessions on global pause with clean status reset - Track and dispose active merger session on global pause via onSession callback - Add JSDoc documenting global pause behavior on executor and triage constructors
This commit is contained in:
@@ -974,4 +974,52 @@ describe("TaskStore", () => {
|
||||
expect(updated.columnMovedAt).toBe(originalMovedAt);
|
||||
});
|
||||
});
|
||||
|
||||
describe("settings:updated event", () => {
|
||||
it("fires on updateSettings with correct old and new values", async () => {
|
||||
const events: { settings: any; previous: any }[] = [];
|
||||
store.on("settings:updated", (data) => events.push(data));
|
||||
|
||||
await store.updateSettings({ maxConcurrent: 5 });
|
||||
|
||||
expect(events).toHaveLength(1);
|
||||
expect(events[0].previous.maxConcurrent).toBe(2); // DEFAULT_SETTINGS value
|
||||
expect(events[0].settings.maxConcurrent).toBe(5);
|
||||
});
|
||||
|
||||
it("includes previous globalPause: false → new globalPause: true when toggled", async () => {
|
||||
const events: { settings: any; previous: any }[] = [];
|
||||
store.on("settings:updated", (data) => events.push(data));
|
||||
|
||||
// Default globalPause is false
|
||||
await store.updateSettings({ globalPause: true });
|
||||
|
||||
expect(events).toHaveLength(1);
|
||||
expect(events[0].previous.globalPause).toBe(false);
|
||||
expect(events[0].settings.globalPause).toBe(true);
|
||||
});
|
||||
|
||||
it("includes previous globalPause: true → new globalPause: false when toggled off", async () => {
|
||||
await store.updateSettings({ globalPause: true });
|
||||
|
||||
const events: { settings: any; previous: any }[] = [];
|
||||
store.on("settings:updated", (data) => events.push(data));
|
||||
|
||||
await store.updateSettings({ globalPause: false });
|
||||
|
||||
expect(events).toHaveLength(1);
|
||||
expect(events[0].previous.globalPause).toBe(true);
|
||||
expect(events[0].settings.globalPause).toBe(false);
|
||||
});
|
||||
|
||||
it("fires on every updateSettings call even when value unchanged", async () => {
|
||||
const events: { settings: any; previous: any }[] = [];
|
||||
store.on("settings:updated", (data) => events.push(data));
|
||||
|
||||
await store.updateSettings({ maxConcurrent: 2 });
|
||||
await store.updateSettings({ maxConcurrent: 2 });
|
||||
|
||||
expect(events).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface TaskStoreEvents {
|
||||
"task:updated": [task: Task];
|
||||
"task:deleted": [task: Task];
|
||||
"task:merged": [result: MergeResult];
|
||||
"settings:updated": [data: { settings: Settings; previous: Settings }];
|
||||
"agent:log": [entry: AgentLogEntry];
|
||||
}
|
||||
|
||||
@@ -130,10 +131,11 @@ export class TaskStore extends EventEmitter<TaskStoreEvents> {
|
||||
async updateSettings(patch: Partial<Settings>): Promise<Settings> {
|
||||
return this.withConfigLock(async () => {
|
||||
const config = await this.readConfig();
|
||||
const current = { ...DEFAULT_SETTINGS, ...config.settings };
|
||||
const updated = { ...current, ...patch };
|
||||
const previous = { ...DEFAULT_SETTINGS, ...config.settings };
|
||||
const updated = { ...previous, ...patch };
|
||||
config.settings = updated;
|
||||
await this.writeConfig(config);
|
||||
this.emit("settings:updated", { settings: updated, previous });
|
||||
return updated;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user