@@ -229,6 +229,43 @@ describe('cli commands', () => {
229229 expect ( output ) . toContain ( 'Template variables applied:' )
230230 } )
231231
232+ it ( 'copies github workflow templates to the workspace root' , async ( ) => {
233+ const root = mkdtempSync ( join ( realTmpdir , 'intent-cli-setup-gha-mono-' ) )
234+ tempDirs . push ( root )
235+
236+ writeJson ( join ( root , 'package.json' ) , {
237+ private : true ,
238+ workspaces : [ 'packages/*' ] ,
239+ } )
240+ writeJson ( join ( root , 'packages' , 'router' , 'package.json' ) , {
241+ name : '@tanstack/router' ,
242+ version : '1.0.0' ,
243+ intent : { version : 1 , repo : 'TanStack/router' , docs : 'docs/' } ,
244+ } )
245+ writeSkillMd ( join ( root , 'packages' , 'router' , 'skills' , 'routing' ) , {
246+ name : 'routing' ,
247+ description : 'Routing skill' ,
248+ } )
249+
250+ process . chdir ( join ( root , 'packages' , 'router' ) )
251+
252+ const exitCode = await main ( [ 'setup-github-actions' ] )
253+ const rootWorkflowsDir = join ( root , '.github' , 'workflows' )
254+ const packageWorkflowsDir = join (
255+ root ,
256+ 'packages' ,
257+ 'router' ,
258+ '.github' ,
259+ 'workflows' ,
260+ )
261+ const output = logSpy . mock . calls . flat ( ) . join ( '\n' )
262+
263+ expect ( exitCode ) . toBe ( 0 )
264+ expect ( existsSync ( rootWorkflowsDir ) ) . toBe ( true )
265+ expect ( existsSync ( packageWorkflowsDir ) ) . toBe ( false )
266+ expect ( output ) . toContain ( 'Mode: monorepo' )
267+ } )
268+
232269 it ( 'lists installed intent packages as json' , async ( ) => {
233270 const root = mkdtempSync ( join ( realTmpdir , 'intent-cli-list-' ) )
234271 tempDirs . push ( root )
@@ -484,6 +521,174 @@ describe('cli commands', () => {
484521
485522 fetchSpy . mockRestore ( )
486523 } )
524+
525+ it ( 'checks only the targeted workspace package for staleness' , async ( ) => {
526+ const root = mkdtempSync ( join ( realTmpdir , 'intent-cli-stale-target-' ) )
527+ tempDirs . push ( root )
528+
529+ writeJson ( join ( root , 'package.json' ) , {
530+ private : true ,
531+ workspaces : [ 'packages/*' ] ,
532+ } )
533+ writeJson ( join ( root , 'packages' , 'router' , 'package.json' ) , {
534+ name : '@tanstack/router' ,
535+ } )
536+ writeJson ( join ( root , 'packages' , 'query' , 'package.json' ) , {
537+ name : '@tanstack/query' ,
538+ } )
539+ writeSkillMd ( join ( root , 'packages' , 'router' , 'skills' , 'routing' ) , {
540+ name : 'routing' ,
541+ description : 'Routing skill' ,
542+ library_version : '1.0.0' ,
543+ } )
544+ writeSkillMd ( join ( root , 'packages' , 'query' , 'skills' , 'cache' ) , {
545+ name : 'cache' ,
546+ description : 'Caching skill' ,
547+ library_version : '1.0.0' ,
548+ } )
549+
550+ const fetchSpy = vi . spyOn ( globalThis , 'fetch' ) . mockResolvedValue ( {
551+ ok : true ,
552+ json : async ( ) => ( { version : '1.0.0' } ) ,
553+ } as Response )
554+
555+ process . chdir ( root )
556+
557+ const exitCode = await main ( [ 'stale' , 'packages/router/skills' , '--json' ] )
558+ const output = logSpy . mock . calls . at ( - 1 ) ?. [ 0 ]
559+ const reports = JSON . parse ( String ( output ) ) as Array < { library : string } >
560+
561+ expect ( exitCode ) . toBe ( 0 )
562+ expect ( reports ) . toHaveLength ( 1 )
563+ expect ( reports [ 0 ] ! . library ) . toBe ( '@tanstack/router' )
564+ expect ( fetchSpy ) . toHaveBeenCalledTimes ( 1 )
565+
566+ fetchSpy . mockRestore ( )
567+ } )
568+
569+ it ( 'checks only the targeted workspace package when path omits /skills suffix' , async ( ) => {
570+ const root = mkdtempSync (
571+ join ( realTmpdir , 'intent-cli-stale-target-nosuffix-' ) ,
572+ )
573+ tempDirs . push ( root )
574+
575+ writeJson ( join ( root , 'package.json' ) , {
576+ private : true ,
577+ workspaces : [ 'packages/*' ] ,
578+ } )
579+ writeJson ( join ( root , 'packages' , 'router' , 'package.json' ) , {
580+ name : '@tanstack/router' ,
581+ } )
582+ writeJson ( join ( root , 'packages' , 'query' , 'package.json' ) , {
583+ name : '@tanstack/query' ,
584+ } )
585+ writeSkillMd ( join ( root , 'packages' , 'router' , 'skills' , 'routing' ) , {
586+ name : 'routing' ,
587+ description : 'Routing skill' ,
588+ library_version : '1.0.0' ,
589+ } )
590+ writeSkillMd ( join ( root , 'packages' , 'query' , 'skills' , 'cache' ) , {
591+ name : 'cache' ,
592+ description : 'Caching skill' ,
593+ library_version : '1.0.0' ,
594+ } )
595+
596+ const fetchSpy = vi . spyOn ( globalThis , 'fetch' ) . mockResolvedValue ( {
597+ ok : true ,
598+ json : async ( ) => ( { version : '1.0.0' } ) ,
599+ } as Response )
600+
601+ process . chdir ( root )
602+
603+ const exitCode = await main ( [ 'stale' , 'packages/router' , '--json' ] )
604+ const output = logSpy . mock . calls . at ( - 1 ) ?. [ 0 ]
605+ const reports = JSON . parse ( String ( output ) ) as Array < { library : string } >
606+
607+ expect ( exitCode ) . toBe ( 0 )
608+ expect ( reports ) . toHaveLength ( 1 )
609+ expect ( reports [ 0 ] ! . library ) . toBe ( '@tanstack/router' )
610+ expect ( fetchSpy ) . toHaveBeenCalledTimes ( 1 )
611+
612+ fetchSpy . mockRestore ( )
613+ } )
614+
615+ it ( 'checks the current workspace package for staleness from package cwd' , async ( ) => {
616+ const root = mkdtempSync ( join ( realTmpdir , 'intent-cli-stale-package-cwd-' ) )
617+ tempDirs . push ( root )
618+
619+ writeJson ( join ( root , 'package.json' ) , {
620+ private : true ,
621+ workspaces : [ 'packages/*' ] ,
622+ } )
623+ writeJson ( join ( root , 'packages' , 'router' , 'package.json' ) , {
624+ name : '@tanstack/router' ,
625+ } )
626+ writeJson ( join ( root , 'packages' , 'query' , 'package.json' ) , {
627+ name : '@tanstack/query' ,
628+ } )
629+ writeSkillMd ( join ( root , 'packages' , 'router' , 'skills' , 'routing' ) , {
630+ name : 'routing' ,
631+ description : 'Routing skill' ,
632+ library_version : '1.0.0' ,
633+ } )
634+ writeSkillMd ( join ( root , 'packages' , 'query' , 'skills' , 'cache' ) , {
635+ name : 'cache' ,
636+ description : 'Caching skill' ,
637+ library_version : '1.0.0' ,
638+ } )
639+
640+ const fetchSpy = vi . spyOn ( globalThis , 'fetch' ) . mockResolvedValue ( {
641+ ok : true ,
642+ json : async ( ) => ( { version : '1.0.0' } ) ,
643+ } as Response )
644+
645+ process . chdir ( join ( root , 'packages' , 'router' ) )
646+
647+ const exitCode = await main ( [ 'stale' , '--json' ] )
648+ const output = logSpy . mock . calls . at ( - 1 ) ?. [ 0 ]
649+ const reports = JSON . parse ( String ( output ) ) as Array < { library : string } >
650+
651+ expect ( exitCode ) . toBe ( 0 )
652+ expect ( reports ) . toHaveLength ( 1 )
653+ expect ( reports [ 0 ] ! . library ) . toBe ( '@tanstack/router' )
654+ expect ( fetchSpy ) . toHaveBeenCalledTimes ( 1 )
655+
656+ fetchSpy . mockRestore ( )
657+ } )
658+
659+ it ( 'handles absolute targetDir path correctly' , async ( ) => {
660+ const root = mkdtempSync ( join ( realTmpdir , 'intent-cli-stale-abs-' ) )
661+ tempDirs . push ( root )
662+
663+ writeJson ( join ( root , 'package.json' ) , {
664+ name : '@tanstack/router' ,
665+ version : '1.0.0' ,
666+ } )
667+ writeSkillMd ( join ( root , 'skills' , 'routing' ) , {
668+ name : 'routing' ,
669+ description : 'Routing skill' ,
670+ library_version : '1.0.0' ,
671+ } )
672+
673+ const fetchSpy = vi . spyOn ( globalThis , 'fetch' ) . mockResolvedValue ( {
674+ ok : true ,
675+ json : async ( ) => ( { version : '1.0.0' } ) ,
676+ } as Response )
677+
678+ const elsewhere = mkdtempSync ( join ( realTmpdir , 'intent-cli-stale-abs-cwd-' ) )
679+ tempDirs . push ( elsewhere )
680+ process . chdir ( elsewhere )
681+
682+ const exitCode = await main ( [ 'stale' , root , '--json' ] )
683+ const output = logSpy . mock . calls . at ( - 1 ) ?. [ 0 ]
684+ const reports = JSON . parse ( String ( output ) ) as Array < { library : string } >
685+
686+ expect ( exitCode ) . toBe ( 0 )
687+ expect ( reports ) . toHaveLength ( 1 )
688+ expect ( reports [ 0 ] ! . library ) . toBe ( '@tanstack/router' )
689+
690+ fetchSpy . mockRestore ( )
691+ } )
487692} )
488693
489694describe ( 'package metadata' , ( ) => {
0 commit comments