fix(agents): keep removed background processes alive until exit (#113860)

* fix(agents): keep removed processes live until exit

* test(agents): isolate process registry lifecycle coverage

* chore(plugin-sdk): refresh API closure baseline
This commit is contained in:
Peter Steinberger
2026-08-09 06:04:40 -07:00
committed by GitHub
parent 8616c0c374
commit cb50289e28
4 changed files with 94 additions and 72 deletions
+31 -31
View File
@@ -3,10 +3,10 @@ df71299237a4752d6b19ab0cf1d3479ca3e1f3ccb4481d96ec09d4c4be4a4c3a module/account
71522995185b956a0cc4927a472cc8d1153e5e998874bfd9a750513175174713 module/account-id
9017717bd6213d60ad3906e92b25f2c7eb02fe47ba1c674b45135913a9d134d1 module/account-resolution
3fe118210b885af40088457ed81ffa5ede18c8e695295731a2ee059af46843cc module/agent-config-primitives
c798cbdd209bdb67c2d2df6e0668a6c1249b9c9890039a572e4372ca930f297d module/agent-harness
3b41f538f9a93a2e46496ccd1cdecab2a1921337230838c96fd1668e4c069714 module/agent-harness-runtime
970afdf69a5844f77c112a98cdea09079e89e42160e8c6c3575301d8f61f6c3f module/agent-harness
1fcceffda9af056eaa1ff062d9d32182dec14b38c46a9f9c67fd848757464d5b module/agent-harness-runtime
773943f0f5cc26d4bfd1dc6cfdac5effc2bec14f1bde927e9e407ab4c9701ba0 module/agent-media-payload
c0e01cbe284a637160e0491a45ed39a615cf6e9ea228c031d8cd29929286a203 module/agent-runtime
e813a1bc92456cfe754cc861083eeff9b19e15b7de5214d33c4b27d112e831b8 module/agent-runtime
241d467d0af5f81d8a535fe0c65d226356daf8325a037cb23092b8dd82aaa456 module/agent-scope-runtime
8fecb210e22bce4532b6ab649b09465f0bd2c857a44abf40db7d683d6491e6da module/allow-from
a089721688670b451885e3100043b2b978709f20fbb06440cdb3f1231b114b65 module/allowlist-config-edit
@@ -26,19 +26,19 @@ d7e53de63b0ac11a266e4abdc18ba6e9401b80309f5c8f5f6a72a00f65dfe3bd module/boolean
c2cc71d5070b6071c51248b0648d1ad1a9468d3737df890adc77ec02025e8853 module/channel-config-primitives
76ad615d374431580ea1755594e2ce3ce047ac1de9fd4621053dca0fbc3afc4d module/channel-config-schema
429a622f16518dc102357238db361966076439c09458d61e0281e2d298f03938 module/channel-contract
5d4af9ddb8bb29fb814b7892e278ac1c49c29c40592026da2b32c8c4c683b36c module/channel-core
987971205d6cda625278fe021234935acb6bbb37966a919d5f56cfc50348f001 module/channel-core
1791224e2302e91d14efd7d3724a4aa0826e6d4df6b766bea27555e031505d75 module/channel-dm-policy
6310b414c8cb81d977a6dbc592b4261bf75fb53b08941ef502f33588e832c62b module/channel-entry-contract
c66bfab080b68e81b98a1d0e1c40c0e67a57c0b38ec401d650841316efc83217 module/channel-entry-contract
2c55b3f3d1d275f760a7e1c78764e4030e7a06c4273a4d51d8f3c82b55ea818d module/channel-feedback
b0100a628d922ec7dca9991e67eb4f47c451eb6ffa064d75efddc5d15f7ce56d module/channel-inbound
7b8baf56da58ae1f7ad194bff8b2731964d712c3df9381248dc9954ab3f2a718 module/channel-inbound
d7e21bb831ad5125e6498e88fcc27e820ed296784eb2296c22795c08d55ade06 module/channel-inbound-debounce
79a8f244b0627ce4b601231bf71f0ee539f6ac7692e490847ec8e7ace7d29f1c module/channel-ingress-runtime
db1c401ab2c5ad89fa801580ac495ba91291de6dba2449aa6b25e0f078469040 module/channel-lifecycle
0e47457e38d1df0bd572e1408cde2ca6a788b65205f43c585316b5ad3a8f2f16 module/channel-logging
e7c775b8ce19927e4fb1248109ee399a57a44d2ea191e3b28d50ef62d8e27390 module/channel-message
afbb8ded2441824fe20ba9038c545215b8d305f9f4a07c5620b5838f8c71da04 module/channel-outbound
39a89f510704905b46829e46676ebcf0e1052309429dc9f77fcaabac22684d6a module/channel-pairing
35734c7db6a4859154f4cd4e541dfbe28311eff6502428eabd6c944135fab468 module/channel-plugin-common
0a050045c2e222cb6e35c53ae79bd6ad6d7fb2b7ba7b82043ab6bc300a801bd6 module/channel-message
8b3b27f38525ed2eabdb74e6b75d89791d64276855060a35cf272fd138d064d1 module/channel-outbound
daa0f059d922b110fe9427b9e37be64730eacafd9e5ab3eae6b92e2f339dcb15 module/channel-pairing
225ef1458c5a757ee00fc5d63728de1123526d3e868b1edc6696953a07614d4b module/channel-plugin-common
06d2928491181215a1814a89f62cae1611ef9b422593bddf12d888a1e6ae91a4 module/channel-policy
a547b035d75d8072b684f343e3d18fb4f87d05fec00b9cc817c6d92d676f2dc9 module/channel-reply-pipeline
482370e60135db9bfaf07f24bab549e5fde09ab265a6061a1f587c5d93929e91 module/channel-runtime-context
@@ -51,8 +51,8 @@ bb5b3388b642d4dac5d42746d9c2b7d6eb69b4057346b6bdcdf4cec7dcb8091c module/channel
67df67da5ae72e9eaeb19d41b6bd2432ec4fd8b7b63b2b616fb98f3b4e0ec41d module/channel-streaming-config
1303df5cc58539c6941e2cd159c93259804c925795219f1630f4d740896a77c1 module/cli-argv
ad12670dbfe538f8d0ebf4fb2b68080e93a760278278e6b1ce9bb129d4b2d533 module/collection-runtime
a324b019218ac9b431afce891eff52a01e4157762c81d42142aa4e44ed0adf17 module/command-auth
479e3ac1cd3ad9766d5b4b9f41c5d8aac66d106c1773ce1b3d5a4f67d70c7465 module/command-auth-native
b4d0b970b4981b7753cbe85aa183f8c67f6053dbbf3bf7513bdb449abedfadb1 module/command-auth
31592f768b5dc36ad241984aa8fb2a69b309e5964de15f5f1fd820d643c63184 module/command-auth-native
a41d9effc1656cbc131611099bdeb81423ab48adce8c1b1ba07100dff8d32818 module/command-detection
31044216c6495728a36dbe60da31f7c1ede2b069cd0d0685d887ebca31814d5f module/command-primitives-runtime
e42cc234ace96a64cec0bdb8051ddded77618e384ae2bbce8b633bf35dbd0288 module/command-status
@@ -60,12 +60,12 @@ e42cc234ace96a64cec0bdb8051ddded77618e384ae2bbce8b633bf35dbd0288 module/command
5e866c4f8dea30045a8a94e037f0e202d597afb1ca221d9854b15bc416503643 module/config-mutation
c66b3cf0f9591dcfcba4b5108d09cd81670aafdb210220d25f86f335b4860da7 module/config-runtime
8b531387918aff0c41ded4233c62c42958a86d110d2e854a393d8bbf35f08599 module/conversation-runtime
c6cd9c0577d8cbe06412d725dff3641dbfdfc5fd579ca3e8a93747e1c0ec7c4a module/core
de7cb98463c8c4e9f326ee873bffeef03f94942f05d7be6d4849fb4294826adc module/dedupe-runtime
41fe16ca85df3caf9701f56518a8ee8d82a6c7a377023d8ab8646b1035bdc50c module/core
7658e5deb657f52d6df0f4a22718c39ee7d3aa5518a1d6cd4d83b395c9c6680b module/dedupe-runtime
ebef0e650ab45e44c9335e2b3e15588c968cea6dadd125364a076f9c50ad1e8c module/device-bootstrap
fd7c489415aa272af724ac15e95d297eac0edeb229e30d02c4061d5276f874b2 module/diagnostic-runtime
b6d5d4acbeb7530ffd06ab34b0f8253b6b3eba9eff2d65e132c4ad506ad5f7c8 module/directory-runtime
24ac4c2fa11402f8c0345613f80b79e5ce0d5be39e6d65ed54e2f6bfca658b8b module/discord
20fe717112030cae06d3991fc4be5551862b217b700e3dc02baa64537f92b41a module/discord
c468c0ca5e5fc093ef5bd0cd15c57e19059bbe5c453d68f2664e9aaa35661cab module/error-runtime
6d9b6396888d7cddded108e211053559b10d79397d20098e0616767be4a4bfb3 module/extension-shared
dd9f6e0fd33cc88b22543c1ee30cc09cf4de4d8f30dff7b7f9cebef885c21543 module/gateway-method-runtime
@@ -75,7 +75,7 @@ e7eb5392bc837947f5f7ad9a66f179316ea8b652207c2124157116a348136bd5 module/gateway
648fdd8d7ea3505342ccb59ac396602b63d589a8b9651b2f39a42f30a8615e6e module/hook-runtime
185a5acedbd7f1a73e5cc773e22bf494b124a09bcd68b5a756ff0f881abf431b module/inbound-envelope
4928af5d2509f696b896f53ac790303a0742202dbcdae3e44fe6d1b434a9c1ba module/inbound-event-delivery
ca78010e064c4791bc9b8c03c59e3f20378eea31bb13c3e763d1884ac5219583 module/inbound-reply-dispatch
7f5e2890a7b2b398b906ec5fd5cf58cc66f4889fa782b803c1af2d9bb43a5b90 module/inbound-reply-dispatch
54b2b398555ac7fe5c7643c809abc4c2d0074305ac9cabd67e7b98ec4f673dc6 module/infra-runtime
ce73721421f1b903dd04ead4df173582e59ea3e9990248102c448b419cc6d272 module/ingress-effect-once
f6c42d02df87ec83486ecfdc73027a628f65f2bbd1a5a0f502adf00d68655740 module/interactive-runtime
@@ -89,28 +89,28 @@ f74d7295fe716aa140aa0bc9300d6259d71dab826de0808fca6bb02592bf5d6e module/media-m
6a52f93107335f88751704352cc01e62add06f854a5b7d765e2a5ee87c0313b6 module/media-store
7dd4a69b33196e946b03a3579e3b569176ff32db22fa668d5eacc06227574cd1 module/media-understanding
d2301239c1beb0b24d33ac49e7bfc6b22c787911a8161def521e024a390a7fa0 module/media-understanding-runtime
043c1077c6e9c076616e831da96067541628210dcc9740d106f376db3f2a86d9 module/meeting-runtime
bc9156c8582298c797fc7404f2dab0f6ab60f536affb0289b68a2f77226a7457 module/meeting-runtime
d16cbced4f2e6672ac9a032ac41691fe7ff4994e328d44ed6ac8a46dbbec834f module/memory-core-host-engine-foundation
d5d9e22a2b30c3116208abfd7451dc98bc4797c4ff2c48294be85018ee0ed141 module/memory-host-core
0e7579fafd9ba2ecab1f359951bebb57126a78ad4b0340c2225bff3b77e81d45 module/memory-host-core
1efa0aadc4261d1c6073058cbf3dcc9fa681424819bdd14333e19b249bbc4b18 module/messaging-targets
b679bab01e041322bc44fd65137931dab638ce50144f7bbd81184fe50ab8c403 module/model-session-runtime
09a9d84368c49f2ada99236a902d5bd7a4ddcb16ed46f93d5a796bb9dd8f3779 module/models-provider-runtime
e00277e19c0572a4fcee74a2a024b149bdc2f678c6cc540757d86b96aca2bff3 module/models-provider-runtime
d7d1843f5958c67cbdcd816aa9a280b534cb7b9d30c6c7441fec34789b973e15 module/native-command-config-runtime
faaa22538f3459cef412c52088cb40dc732aa560fba2e70655938460022287d0 module/native-command-registry
5b968ecbef95fda927d0944409994e355ec878608dd084358970078d2ac545a9 module/param-readers
ca7a56bb1a6169b4cf9befbf5aa21da280a8086fdc49fca4eec520a7a7c98549 module/persistent-dedupe
1bf4d4dfe5a4b264cf6fb8fbd0c7bc76f520ff9845cffad6da4b3a3c2bc3f6f6 module/plugin-config-runtime
3d253774c067dff607d431cd52a675561dda0922cf15187060f8a5121adfb821 module/plugin-entry
86a216e0fc5228c5b68ff34d635d89cfa143a908530c7f1b34bec14b3cf38499 module/plugin-runtime
8a935eaf3eeda274a89f96bf34f2b21fcd869e2ddf3e39ed9316ce05f0cdbdcc module/provider-auth
a9084307a59c21eaffaafa2475d8640b75b21ee46abf4d1f0a17a18d1d51d033 module/provider-catalog-runtime
36a0703966afa0b1358e2c41605a72bc9ff4cbec41081ed72e57671ed7642443 module/plugin-entry
6d6fb53d4d06652267860a31bd011049d23d98170bfd1aaab13281fbd771390a module/plugin-runtime
e36cc7a004a62c477b5b9607300ffaac29dae0c04a969c80cb3e9e34c1ed8513 module/provider-auth
b73d1476f0167eafbe9a2b4ce121abc83243d0805d602c0a889e2b7d6b5e74e4 module/provider-catalog-runtime
8131147d699394bd06503e2ea2f5f1a50b1594a87dded6d118b74a8d0328c8f6 module/proxy-capture
69a2931ee70410d6e782c0e6f4ea1964a9f72651999070c7453eb6c992ba6cc8 module/question-gateway-runtime
ca1cc8a9cd34068aceb2a96cae9c02f2cb4b9a09d7cf6124a588c21be2d7719d module/reply-chunking
f8855dfcac8ae3b06dcdd448731ef5269e9bf55f12db3dbc882a0f9291c25859 module/reply-dispatch-runtime
bd17821de25a20bbc308a19911cc45cb7be7e9bcd4e0444ab09ab0abcd405dab module/reply-dispatch-runtime
73f861fa3179d5af1159853c5acab0eec7a6c8f9398dcb75ea770e784fca6727 module/reply-history
e023767a2b193c8404b3a2992cad4c5b71d944c2ffa29ddf180749d488d84721 module/reply-payload
40fae07882914b2fb71c0eb9bb91760be1900d45a5044673df799feb3d39055a module/reply-runtime
fcbf5ff7646fb07cc12d8f1015424f34180b4f0d92f42d4d46e7bc1f0f80ca13 module/reply-runtime
aa07d85d99fdd2b1e0cbe9975fb6dcae66b8bdce2607c6bd5402ae68bb15118c module/root-walk
e26cc92679c768fa1474f15828f545aec87f32718a6b35f7907c4f56f65542fc module/routing
7877a7e58fa32a64107154e5b714c6d165e96989d4aa5f43e0afac085a187af0 module/run-command
@@ -118,20 +118,20 @@ c83779c80c9e7b196b31a39ec4b986098bd701b089bf6eb2f53c368fb982ea77 module/runtime
159b563aad773cef67f18bf9bd2653420bec94b599e052f2a1d5a238bf341e16 module/runtime-config-snapshot
9fe5bcb52b462010214eda1c01f60b3a018837d9f95dc864f6d457cb3da001cf module/runtime-env
7e871b7319745678bb83fcfc1b54c8751b0ab1af92ff06c01d0659ac92863c11 module/runtime-group-policy
54357ac67298c6dd7d2132dc56b30cd90391074cc8e1c403ee5a117f4f82855b module/runtime-store
e9f361ecc3895454c6e4629f198c95324e0c6f2b306c89962baefc64b00a6bb5 module/runtime-store
d17862c40825af1ddf0257b44f1e1cbb9c375e8e5ed668fae75d530d1a465cf9 module/secret-file
8e2ac4d3973d8d8ce4478e3440d66ee5c0d9213b0fe9e927c421d14fd31e5e86 module/secret-input
e7672788f052a1249839c8fa24d6a9a45967c4e3fd94e890b0f90296026cd1ca module/secret-input-runtime
026631cbf010d0325be2c4fa4ccd8bbdf8e1008f0904c742c270811f578b07b8 module/secret-ref-runtime
6a642666b8615801d4ddde14f6d96f8e9d86c152990ec6ca95e135cd567bb1d8 module/security-runtime
8d71964ef52c2b93a809fe25ea293770aa203ffd9c7d6f871f32f815ddf8626e module/session-catalog
72391cbf04720fd4c44d4ccda9bc5d2e82fee27fd4113a4183b05a7d5b2f7746 module/session-discussion
9bec400cbd03d0b9ccd3a1a36aeb1caacb908d97c872b0142acba4cb7c92f729 module/session-catalog
3dd2079c6a6fed3deb7b7fea9a7ca9677e8cee46affea7f3a200c7f9dcaf82d1 module/session-discussion
96b770e79104743ea4476b4cea24aace91d6434491d2c46efd63eb64aa113b3c module/session-store-runtime
4a73a7c32b0dd2ac0a7bd5baf320aef0c7a3cc917eee009e18a4d62edc0fd855 module/setup
32591a4713689552df4bd4533b439a49d9540835cc041e76844157707ea4867b module/setup-runtime
44d37e0d9131ad2859f41068f2604090c784e65f1bd6ebda8e051b6f2e5e1660 module/setup-tools
569fd20d35765b74889bfc853eec39b8240e595717fbc21bc0fec0e4b7c3ca2e module/skill-commands-runtime
9e9177d319daeb1219087d8b05375e3cc9c0e0a27514b2d56ec7cea14dede7b4 module/speech-settings
c18afe6ed1cb586a5e7b6d286e9a9371862246a9a76d68ae541040fe0b2fed48 module/speech-settings
a4c6c4173cfdb87988720f7f150e1698bb4b21080864e89fd64587d290544bb0 module/ssrf-policy
0d1a1fdd27724bcb07f2276b015e9dd278cbd4e99dd2ddb628b50a52e533335b module/ssrf-runtime
5501c65f90feec38049ce100cb320b2a629ebf1ad04b21f015a0d44aa1e4c448 module/state-paths
@@ -141,11 +141,11 @@ c2aca425088c2bc9a74035f34d8b541354792eb0c44b988e314d59c25ac3aa7f module/telegra
aef35bee2502cd6ed8765409b758e452aff8ac9469fd773e6a2a44c9a1bc3f66 module/temp-path
87fa81b9e58d8fc04a4b4202d2d37fca339615f5225687d9db905151439e0f4d module/text-chunking
434804a2166f6bf2e872bff0f03f3af850e44dea04b49b1d13b41df872bb71d1 module/text-runtime
055729e20d56d47a0be9a77a1018d2b56959bc4e54a9d610bc722b7cbdaed228 module/tool-plugin
b7995540c794ee0e1223de9c071bad408029a895f931a6a1d02cc5dc6be0939a module/tool-plugin
dc1a073c59ab61e2789533b777b3f0cb9af689d64a97796b10e8aa82552510db module/tool-results
8c47283ce8caf5008363cd8bc93f5db913f90ba7e2f13b38aa1dbc35cf0083c1 module/tool-send
cda105b721d498df23a554c6b68be150b8fe66b8b9172185c31a0b3b0646b1dc module/web-media
748a1a78cb4f203245101268df60770ff5fa4c88a106218c4b5886218b650f08 module/webhook-ingress
7ec9da302ca6818e98dad2b4dc4b8661d830f28765427855fb3449d76e803e83 module/webhook-ingress
a107b97d3c1bb7494e516760d613950d30dbf57ccaea4b037e2e832ca6115839 module/webhook-request-guards
de59e86e126b75d13251cba7ebbe27b44d9b5588785d98df5ff4d6722374c81f module/widget-html
9161b36ec0ab062ea41b363c894fcd672a7727f21cb726739f99f9c184fce69d module/zod
+2 -3
View File
@@ -1,10 +1,9 @@
// Shared control seam for task-ledger and process-tool cancellation.
import { getProcessSupervisor } from "../process/supervisor/index.js";
import { getSession } from "./bash-process-registry.js";
import { getSession, hasActiveBackgroundExecSession } from "./bash-process-registry.js";
export function isBackgroundExecSessionActive(sessionId: string): boolean {
const session = getSession(sessionId);
return Boolean(session?.backgrounded && !session.exited);
return hasActiveBackgroundExecSession(sessionId);
}
export function cancelBackgroundExecSession(sessionId: string): boolean {
+5
View File
@@ -304,6 +304,11 @@ export function acknowledgeNotifyOnExit(record: {
record.notifyOnExitRemoval = undefined;
}
/** Reports owner-tracked process liveness even after visibility is removed. */
export function hasActiveBackgroundExecSession(sessionId: string): boolean {
return activeBackgroundExecSessionIds.has(sessionId);
}
/** Returns the number of live background exec sessions without exposing process details. */
export function getActiveBackgroundExecSessionCount(): number {
return activeBackgroundExecSessionIds.size;
+56 -38
View File
@@ -2701,47 +2701,65 @@ describe("task-registry", () => {
});
});
it("retains live background exec tasks and marks missing process sessions lost", async () => {
await withTaskRegistryTempDir(async () => {
resetTaskRegistryMemoryForTest();
const task = createTaskFixture("cli", {
taskKind: "exec",
sourceId: "amber-reef",
runId: "exec:amber-reef",
task: "Background CLI command",
lastEventAt: Date.now() - 10 * 60_000,
});
const currentTasks = new Map([[task.taskId, task]]);
configureTaskRegistryMaintenanceRuntimeForTest({
currentTasks,
snapshotTasks: [task],
isBackgroundExecSessionActive: () => true,
});
it("retains removed background exec tasks until the process exits", async () => {
const [
{ isBackgroundExecSessionActive },
{ addSession, deleteSession, markBackgrounded, markExited },
{ createProcessSessionFixture },
{ resetProcessRegistryForTests },
] = await Promise.all([
import("../agents/bash-process-control.js"),
import("../agents/bash-process-registry.js"),
import("../agents/bash-process-registry.test-helpers.js"),
import("../agents/bash-process-registry.test-support.js"),
]);
resetProcessRegistryForTests();
try {
await withTaskRegistryTempDir(async () => {
resetTaskRegistryMemoryForTest();
const session = createProcessSessionFixture({ id: "amber-reef" });
addSession(session);
markBackgrounded(session);
deleteSession(session.id);
expect(await runTaskRegistryMaintenance()).toEqual({
reconciled: 0,
recovered: 0,
cleanupStamped: 0,
pruned: 0,
});
expectRecordFields(currentTasks.get(task.taskId), { status: "running" });
const task = createTaskFixture("cli", {
taskKind: "exec",
sourceId: session.id,
runId: `exec:${session.id}`,
task: "Background CLI command",
lastEventAt: Date.now() - 10 * 60_000,
});
const currentTasks = new Map([[task.taskId, task]]);
configureTaskRegistryMaintenanceRuntimeForTest({
currentTasks,
snapshotTasks: [task],
isBackgroundExecSessionActive,
});
configureTaskRegistryMaintenanceRuntimeForTest({
currentTasks,
snapshotTasks: [task],
isBackgroundExecSessionActive: () => false,
expect(await runTaskRegistryMaintenance()).toEqual({
reconciled: 0,
recovered: 0,
cleanupStamped: 0,
pruned: 0,
});
expectRecordFields(currentTasks.get(task.taskId), { status: "running" });
markExited(session, null, "SIGTERM", "killed");
expect(await runTaskRegistryMaintenance()).toEqual({
reconciled: 1,
recovered: 0,
cleanupStamped: 0,
pruned: 0,
});
expectRecordFields(currentTasks.get(task.taskId), {
status: "lost",
error: "backing session missing",
});
});
expect(await runTaskRegistryMaintenance()).toEqual({
reconciled: 1,
recovered: 0,
cleanupStamped: 0,
pruned: 0,
});
expectRecordFields(currentTasks.get(task.taskId), {
status: "lost",
error: "backing session missing",
});
});
} finally {
resetProcessRegistryForTests();
}
});
it("projects inspection-time orphaned tasks as lost without mutating the registry", async () => {