@@ -1885,7 +1885,7 @@ describe("task-registry", () => {
18851885 } ) ;
18861886 } ) ;
18871887
1888- it ( "does not mark codex-native subagent tasks lost when they have no OpenClaw child session " , async ( ) => {
1888+ it ( "keeps fresh childless codex-native subagent tasks live " , async ( ) => {
18891889 await withTaskRegistryTempDir ( async ( root ) => {
18901890 process . env . OPENCLAW_STATE_DIR = root ;
18911891 resetTaskRegistryForTests ( ) ;
@@ -1914,14 +1914,49 @@ describe("task-registry", () => {
19141914 cleanupStamped : 0 ,
19151915 pruned : 0 ,
19161916 } ) ;
1917- expect ( getTaskById ( task . taskId ) ) . toEqual ( {
1918- ...task ,
1919- createdAt : now - 10 * 60_000 ,
1917+ expectRecordFields ( requireTaskById ( task . taskId ) , {
1918+ status : "running" ,
19201919 lastEventAt : now - 10 * 60_000 ,
19211920 } ) ;
19221921 } ) ;
19231922 } ) ;
19241923
1924+ it ( "marks stale childless codex-native subagent tasks lost" , async ( ) => {
1925+ await withTaskRegistryTempDir ( async ( root ) => {
1926+ process . env . OPENCLAW_STATE_DIR = root ;
1927+ resetTaskRegistryForTests ( ) ;
1928+ const now = Date . now ( ) ;
1929+
1930+ const task = createTaskRecord ( {
1931+ runtime : "subagent" ,
1932+ taskKind : "codex-native" ,
1933+ ownerKey : "agent:main:main" ,
1934+ scopeKind : "session" ,
1935+ sourceId : "codex-thread:child-thread" ,
1936+ runId : "codex-thread:child-thread" ,
1937+ task : "Codex native child" ,
1938+ status : "running" ,
1939+ deliveryStatus : "not_applicable" ,
1940+ notifyPolicy : "silent" ,
1941+ } ) ;
1942+ setTaskTimingById ( {
1943+ taskId : task . taskId ,
1944+ lastEventAt : now - 31 * 60_000 ,
1945+ } ) ;
1946+
1947+ expect ( await runTaskRegistryMaintenance ( ) ) . toEqual ( {
1948+ reconciled : 1 ,
1949+ recovered : 0 ,
1950+ cleanupStamped : 0 ,
1951+ pruned : 0 ,
1952+ } ) ;
1953+ expectRecordFields ( requireTaskById ( task . taskId ) , {
1954+ status : "lost" ,
1955+ error : "Codex native subagent stopped reporting progress" ,
1956+ } ) ;
1957+ } ) ;
1958+ } ) ;
1959+
19251960 it ( "closes terminal parent-owned one-shot ACP sessions during maintenance" , async ( ) => {
19261961 await withTaskRegistryTempDir ( async ( root ) => {
19271962 process . env . OPENCLAW_STATE_DIR = root ;
@@ -3168,7 +3203,7 @@ describe("task-registry", () => {
31683203 } ) ;
31693204 } ) ;
31703205
3171- it ( "does not route codex-native task cancellation through OpenClaw subagent sessions" , async ( ) => {
3206+ it ( "cancels childless codex-native tasks without routing through OpenClaw subagent sessions" , async ( ) => {
31723207 await withTaskRegistryTempDir ( async ( root ) => {
31733208 process . env . OPENCLAW_STATE_DIR = root ;
31743209 resetTaskRegistryForTests ( ) ;
@@ -3190,11 +3225,17 @@ describe("task-registry", () => {
31903225 taskId : task . taskId ,
31913226 } ) ;
31923227
3193- expect ( result ) . toEqual ( {
3228+ expectRecordFields ( result , {
31943229 found : true ,
3195- cancelled : false ,
3196- reason : "Task has no cancellable child session." ,
3197- task,
3230+ cancelled : true ,
3231+ } ) ;
3232+ expectRecordFields ( result . task , {
3233+ taskId : task . taskId ,
3234+ status : "cancelled" ,
3235+ endedAt : expect . any ( Number ) ,
3236+ lastEventAt : expect . any ( Number ) ,
3237+ cleanupAfter : expect . any ( Number ) ,
3238+ error : "Cancelled by operator." ,
31983239 } ) ;
31993240 expect ( hoisted . killSubagentRunAdminMock ) . not . toHaveBeenCalled ( ) ;
32003241 } ) ;
0 commit comments