@@ -325,6 +325,46 @@ describe("skills-clawhub", () => {
325325 } ) ;
326326 } ) ;
327327
328+ it ( "passes forceInstall to the ClawHub install resolver" , async ( ) => {
329+ const commit = "b" . repeat ( 40 ) ;
330+ fetchClawHubSkillInstallResolutionMock . mockResolvedValueOnce ( {
331+ ok : true ,
332+ slug : "aiq-deploy" ,
333+ installKind : "github" ,
334+ github : {
335+ repo : "NVIDIA/skills" ,
336+ path : "skills/aiq-deploy" ,
337+ commit,
338+ contentHash : "hash-aiq-deploy" ,
339+ sourceUrl : `https://github.com/NVIDIA/skills/tree/${ commit } /skills/aiq-deploy` ,
340+ } ,
341+ } ) ;
342+ withExtractedArchiveRootMock . mockImplementationOnce ( async ( params ) => {
343+ return await params . onExtracted ( "/tmp/extracted-github-repo" ) ;
344+ } ) ;
345+ installPackageDirMock . mockResolvedValueOnce ( {
346+ ok : true ,
347+ targetDir : "/tmp/workspace/skills/aiq-deploy" ,
348+ } ) ;
349+
350+ const result = await installSkillFromClawHub ( {
351+ workspaceDir : "/tmp/workspace" ,
352+ slug : "aiq-deploy" ,
353+ forceInstall : true ,
354+ } ) ;
355+
356+ expect ( fetchClawHubSkillInstallResolutionMock ) . toHaveBeenCalledWith ( {
357+ slug : "aiq-deploy" ,
358+ baseUrl : undefined ,
359+ forceInstall : true ,
360+ } ) ;
361+ expectInstalledSkill ( result , {
362+ slug : "aiq-deploy" ,
363+ version : commit ,
364+ targetDir : "/tmp/workspace/skills/aiq-deploy" ,
365+ } ) ;
366+ } ) ;
367+
328368 it ( "keeps ClawHub install telemetry best-effort" , async ( ) => {
329369 reportClawHubSkillInstallTelemetryMock . mockRejectedValueOnce ( new Error ( "telemetry down" ) ) ;
330370
@@ -458,6 +498,40 @@ describe("skills-clawhub", () => {
458498 }
459499 } ) ;
460500
501+ it ( "passes forceInstall to resolver for tracked updates" , async ( ) => {
502+ const slug = "agentreceipt" ;
503+ const { workspaceDir } = await createLegacyTrackedSkillFixture ( slug ) ;
504+ fetchClawHubSkillInstallResolutionMock . mockResolvedValueOnce ( {
505+ ok : true ,
506+ slug,
507+ installKind : "archive" ,
508+ archive : {
509+ version : "1.0.0" ,
510+ downloadUrl : `https://legacy.clawhub.ai/api/v1/download?slug=${ encodeURIComponent ( slug ) } &version=1.0.0` ,
511+ } ,
512+ } ) ;
513+ installPackageDirMock . mockResolvedValueOnce ( {
514+ ok : true ,
515+ targetDir : path . join ( workspaceDir , "skills" , slug ) ,
516+ } ) ;
517+
518+ try {
519+ const results = await updateSkillsFromClawHub ( {
520+ workspaceDir,
521+ forceInstall : true ,
522+ } ) ;
523+
524+ expect ( fetchClawHubSkillInstallResolutionMock ) . toHaveBeenCalledWith ( {
525+ slug,
526+ baseUrl : "https://legacy.clawhub.ai" ,
527+ forceInstall : true ,
528+ } ) ;
529+ expectLegacyUpdateSuccess ( results , workspaceDir , slug ) ;
530+ } finally {
531+ await fs . rm ( workspaceDir , { recursive : true , force : true } ) ;
532+ }
533+ } ) ;
534+
461535 it ( "updates a legacy Unicode slug when requested explicitly" , async ( ) => {
462536 const slug = "re\u0430ct" ;
463537 const { workspaceDir } = await createLegacyTrackedSkillFixture ( slug ) ;
0 commit comments