@@ -3,7 +3,7 @@ import { randomUUID } from "node:crypto";
33import fs from "node:fs/promises" ;
44import path from "node:path" ;
55import { expectDefined } from "@openclaw/normalization-core" ;
6- import { afterEach , beforeEach , describe , expect , it } from "vitest" ;
6+ import { afterEach , beforeEach , describe , expect , it , vi } from "vitest" ;
77import {
88 clearInternalHooks ,
99 registerInternalHook ,
@@ -495,6 +495,7 @@ describe("hasCompletedBootstrapTurn", () => {
495495 } ) ;
496496
497497 afterEach ( async ( ) => {
498+ vi . restoreAllMocks ( ) ;
498499 await fs . rm ( tmpDir , { recursive : true , force : true } ) ;
499500 } ) ;
500501
@@ -640,6 +641,37 @@ describe("hasCompletedBootstrapTurn", () => {
640641 expect ( await hasCompletedBootstrapTurn ( sessionFile ) ) . toBe ( true ) ;
641642 } ) ;
642643
644+ it ( "finds a recent full bootstrap marker when the tail read returns short" , async ( ) => {
645+ const sessionFile = path . join ( tmpDir , "short-read-tail.jsonl" ) ;
646+ const lines = [
647+ JSON . stringify ( { type : "message" , message : { role : "user" , content : "hello" } } ) ,
648+ JSON . stringify ( { type : "message" , message : { role : "assistant" , content : "hi" } } ) ,
649+ JSON . stringify ( {
650+ type : "custom" ,
651+ customType : FULL_BOOTSTRAP_COMPLETED_CUSTOM_TYPE ,
652+ data : { timestamp : 1 } ,
653+ } ) ,
654+ ] ;
655+ await fs . writeFile ( sessionFile , `${ lines . join ( "\n" ) } \n` , "utf8" ) ;
656+
657+ const realOpen = fs . open . bind ( fs ) ;
658+ vi . spyOn ( fs , "open" ) . mockImplementation ( async ( ...args ) => {
659+ const handle = await realOpen ( ...args ) ;
660+ const realRead = handle . read . bind ( handle ) ;
661+ return new Proxy ( handle , {
662+ get ( target , prop , receiver ) {
663+ if ( prop === "read" ) {
664+ return ( buffer : Buffer , offset : number , length : number , position : number ) =>
665+ realRead ( buffer , offset , Math . min ( length , 16 ) , position ) ;
666+ }
667+ return Reflect . get ( target , prop , receiver ) ;
668+ } ,
669+ } ) ;
670+ } ) ;
671+
672+ expect ( await hasCompletedBootstrapTurn ( sessionFile ) ) . toBe ( true ) ;
673+ } ) ;
674+
643675 it ( "returns false for symbolic links" , async ( ) => {
644676 const realFile = path . join ( tmpDir , "real.jsonl" ) ;
645677 const linkFile = path . join ( tmpDir , "link.jsonl" ) ;
0 commit comments