@@ -47,6 +47,17 @@ function runProbeStatus(
4747 }
4848}
4949
50+ function runProbeFileStatus (
51+ command : string ,
52+ filePath : string ,
53+ ) : { status : number | null ; stderr : string } {
54+ const result = spawnSync ( "node" , [ PLUGIN_UPDATE_PROBE_SCRIPT , command , filePath ] , {
55+ encoding : "utf8" ,
56+ stdio : "pipe" ,
57+ } ) ;
58+ return { status : result . status , stderr : result . stderr } ;
59+ }
60+
5061describe ( "plugin update unchanged Docker E2E" , ( ) => {
5162 it ( "seeds current plugin install ledger state before checking config stability" , ( ) => {
5263 const runner = readFileSync ( PLUGIN_UPDATE_DOCKER_SCRIPT , "utf8" ) ;
@@ -75,6 +86,56 @@ describe("plugin update unchanged Docker E2E", () => {
7586 ) ;
7687 expect ( script ) . toContain ( '"--- plugin update output ---"' ) ;
7788 expect ( script ) . toContain ( '"--- local registry output ---"' ) ;
89+ expect ( script ) . toContain ( "openclaw_e2e_print_log /tmp/plugin-update-output.log" ) ;
90+ expect ( script ) . toContain ( "openclaw_e2e_print_log /tmp/openclaw-e2e-registry.log" ) ;
91+ expect ( script ) . not . toContain ( "cat /tmp/plugin-update-output.log" ) ;
92+ expect ( script ) . not . toContain ( "cat /tmp/openclaw-e2e-registry.log" ) ;
93+ } ) ;
94+
95+ it ( "bounds assert-output diagnostics to the saved command log tail" , ( ) => {
96+ const root = mkdtempSync ( path . join ( tmpdir ( ) , "openclaw-plugin-update-probe-" ) ) ;
97+ const logPath = path . join ( root , "plugin-update-output.log" ) ;
98+ try {
99+ writeFileSync (
100+ logPath ,
101+ `DO_NOT_PRINT_OLD_PLUGIN_UPDATE_LOG\n${ "filler line\n" . repeat ( 12 * 1024 ) } missing marker tail` ,
102+ "utf8" ,
103+ ) ;
104+
105+ const result = runProbeFileStatus ( "assert-output" , logPath ) ;
106+
107+ expect ( result . status ) . toBe ( 1 ) ;
108+ expect ( result . stderr ) . toContain ( "Expected up-to-date output missing" ) ;
109+ expect ( result . stderr ) . toContain ( "Output tail:" ) ;
110+ expect ( result . stderr ) . toContain ( "missing marker tail" ) ;
111+ expect ( result . stderr ) . not . toContain ( "DO_NOT_PRINT_OLD_PLUGIN_UPDATE_LOG" ) ;
112+ expect ( result . stderr . length ) . toBeLessThan ( 80 * 1024 ) ;
113+ } finally {
114+ rmSync ( root , { recursive : true , force : true } ) ;
115+ }
116+ } ) ;
117+
118+ it ( "detects unexpected download output before a large log tail" , ( ) => {
119+ const root = mkdtempSync ( path . join ( tmpdir ( ) , "openclaw-plugin-update-probe-" ) ) ;
120+ const logPath = path . join ( root , "plugin-update-output.log" ) ;
121+ try {
122+ writeFileSync (
123+ logPath ,
124+ [
125+ "Downloading @example/lossless-claw" ,
126+ "filler line\n" . repeat ( 12 * 1024 ) ,
127+ "lossless-claw is up to date (0.9.0)." ,
128+ ] . join ( "\n" ) ,
129+ "utf8" ,
130+ ) ;
131+
132+ const result = runProbeFileStatus ( "assert-output" , logPath ) ;
133+
134+ expect ( result . status ) . toBe ( 1 ) ;
135+ expect ( result . stderr ) . toContain ( "Unexpected npm download/reinstall path" ) ;
136+ } finally {
137+ rmSync ( root , { recursive : true , force : true } ) ;
138+ }
78139 } ) ;
79140
80141 it ( "waits for the local registry process during cleanup" , ( ) => {
0 commit comments