@@ -297,10 +297,375 @@ function transformForCodex(content, options) {
297297 return content ;
298298}
299299
300+ /**
301+ * Transform content for Cursor (.mdc rule files).
302+ *
303+ * MDC format uses YAML frontmatter with `description`, `globs`, and
304+ * `alwaysApply` fields followed by a markdown body.
305+ *
306+ * @param {string } content - Source markdown content (may have frontmatter)
307+ * @param {Object } options
308+ * @param {string } options.description - Rule description
309+ * @param {string } options.pluginInstallPath - Absolute path to plugin install dir
310+ * @param {string } [options.globs] - Optional glob pattern for file matching
311+ * @param {boolean } [options.alwaysApply] - Whether rule always applies (default true)
312+ * @returns {string } Transformed MDC content
313+ */
314+ function transformRuleForCursor ( content , options ) {
315+ const { description = '' , pluginInstallPath, globs = '' , alwaysApply = true } = options ;
316+
317+ // Strip control characters and escape description for YAML
318+ const cleanDescription = description . replace ( / [ \x00 - \x1f \x7f ] / g, ' ' ) ;
319+ const escapedDescription = cleanDescription . replace ( / \\ / g, '\\\\' ) . replace ( / " / g, '\\"' ) ;
320+ const yamlDescription = `"${ escapedDescription } "` ;
321+
322+ // Build MDC frontmatter
323+ let frontmatter = `---\ndescription: ${ yamlDescription } \n` ;
324+ if ( globs ) {
325+ frontmatter += `globs: ${ JSON . stringify ( globs ) } \n` ;
326+ }
327+ frontmatter += `alwaysApply: ${ alwaysApply } \n---\n` ;
328+
329+ // Strip existing frontmatter if present
330+ if ( content . startsWith ( '---' ) ) {
331+ content = content . replace ( / ^ - - - \n [ \s \S ] * ?\n - - - \n ? / , '' ) ;
332+ }
333+
334+ content = frontmatter + content ;
335+
336+ // Replace PLUGIN_ROOT paths with actual install path
337+ // Use function replacement to avoid $ pattern interpretation in replacement string
338+ content = content . replace ( / \$ \{ C L A U D E _ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
339+ content = content . replace ( / \$ C L A U D E _ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
340+ content = content . replace ( / \$ \{ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
341+ content = content . replace ( / \$ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
342+
343+ // Strip Claude-specific syntax: Task tool calls (handles one level of nested braces)
344+ content = content . replace ( / a w a i t \s + T a s k \s * \( \s * \{ [ ^ { } ] * (?: \{ [ ^ { } ] * \} [ ^ { } ] * ) * \} \s * \) ; ? / g, ( match ) => {
345+ const agentMatch = match . match ( / s u b a g e n t _ t y p e : \s * [ " ' ] (?: [ ^ " ' : ] + : ) ? ( [ ^ " ' ] + ) [ " ' ] / ) ;
346+ if ( agentMatch ) {
347+ return `Invoke the ${ agentMatch [ 1 ] } agent` ;
348+ }
349+ return '' ;
350+ } ) ;
351+
352+ // Strip require() statements
353+ content = content . replace ( / (?: c o n s t | l e t | v a r ) \s + \{ ? [ ^ } = \n ] + \} ? \s * = \s * r e q u i r e \s * \( [ ^ ) ] + \) ; ? / g, '' ) ;
354+ content = content . replace ( / r e q u i r e \s * \( [ ' " ] [ ^ ' " ] + [ ' " ] \) / g, '' ) ;
355+
356+ // Strip plugin namespacing (e.g. next-task:agent-name -> agent-name)
357+ content = content . replace ( / (?: n e x t - t a s k | d e s l o p | s h i p | s y n c - d o c s | a u d i t - p r o j e c t | e n h a n c e | p e r f | r e p o - m a p | d r i f t - d e t e c t | c o n s u l t | d e b a t e | l e a r n | w e b - c t l ) : ( [ a - z ] [ a - z 0 - 9 - ] * ) / g, '$1' ) ;
358+
359+ return content ;
360+ }
361+
362+ /**
363+ * Transform skill content for Cursor.
364+ *
365+ * Minimal transform - Cursor reads SKILL.md frontmatter natively so we
366+ * preserve it. Only replaces PLUGIN_ROOT paths and strips namespace prefixes.
367+ *
368+ * @param {string } content - Source SKILL.md content
369+ * @param {Object } options
370+ * @param {string } options.pluginInstallPath - Absolute path to plugin install dir
371+ * @returns {string } Transformed skill content
372+ */
373+ function transformSkillForCursor ( content , options ) {
374+ const { pluginInstallPath } = options ;
375+
376+ // Replace PLUGIN_ROOT paths with actual install path
377+ content = content . replace ( / \$ \{ C L A U D E _ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
378+ content = content . replace ( / \$ C L A U D E _ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
379+ content = content . replace ( / \$ \{ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
380+ content = content . replace ( / \$ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
381+
382+ // Strip plugin namespacing (e.g. next-task:agent-name -> agent-name)
383+ content = content . replace ( / (?: n e x t - t a s k | d e s l o p | s h i p | s y n c - d o c s | a u d i t - p r o j e c t | e n h a n c e | p e r f | r e p o - m a p | d r i f t - d e t e c t | c o n s u l t | d e b a t e | l e a r n | w e b - c t l ) : ( [ a - z ] [ a - z 0 - 9 - ] * ) / g, '$1' ) ;
384+
385+ return content ;
386+ }
387+
388+ /**
389+ * Transform command content for Cursor.
390+ *
391+ * Light transform - strips frontmatter, replaces PLUGIN_ROOT paths,
392+ * removes require() statements and Task() calls, strips namespace prefixes.
393+ *
394+ * @param {string } content - Source command markdown content
395+ * @param {Object } options
396+ * @param {string } options.pluginInstallPath - Absolute path to plugin install dir
397+ * @returns {string } Transformed command content
398+ */
399+ function transformCommandForCursor ( content , options ) {
400+ const { pluginInstallPath } = options ;
401+
402+ // Strip existing frontmatter if present
403+ if ( content . startsWith ( '---' ) ) {
404+ content = content . replace ( / ^ - - - \n [ \s \S ] * ?\n - - - \n ? / , '' ) ;
405+ }
406+
407+ // Replace PLUGIN_ROOT paths with actual install path
408+ content = content . replace ( / \$ \{ C L A U D E _ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
409+ content = content . replace ( / \$ C L A U D E _ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
410+ content = content . replace ( / \$ \{ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
411+ content = content . replace ( / \$ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
412+
413+ // Strip require() statements
414+ content = content . replace ( / (?: c o n s t | l e t | v a r ) \s + \{ ? [ ^ } = \n ] + \} ? \s * = \s * r e q u i r e \s * \( [ ^ ) ] + \) ; ? / g, '' ) ;
415+ content = content . replace ( / r e q u i r e \s * \( [ ' " ] [ ^ ' " ] + [ ' " ] \) / g, '' ) ;
416+
417+ // Strip Claude-specific syntax: Task tool calls (handles one level of nested braces)
418+ content = content . replace ( / a w a i t \s + T a s k \s * \( \s * \{ [ ^ { } ] * (?: \{ [ ^ { } ] * \} [ ^ { } ] * ) * \} \s * \) ; ? / g, ( match ) => {
419+ const agentMatch = match . match ( / s u b a g e n t _ t y p e : \s * [ " ' ] (?: [ ^ " ' : ] + : ) ? ( [ ^ " ' ] + ) [ " ' ] / ) ;
420+ if ( agentMatch ) {
421+ return `Invoke the ${ agentMatch [ 1 ] } agent` ;
422+ }
423+ return '' ;
424+ } ) ;
425+
426+ // Strip plugin namespacing (e.g. next-task:agent-name -> agent-name)
427+ content = content . replace ( / (?: n e x t - t a s k | d e s l o p | s h i p | s y n c - d o c s | a u d i t - p r o j e c t | e n h a n c e | p e r f | r e p o - m a p | d r i f t - d e t e c t | c o n s u l t | d e b a t e | l e a r n | w e b - c t l ) : ( [ a - z ] [ a - z 0 - 9 - ] * ) / g, '$1' ) ;
428+
429+ return content ;
430+ }
431+
432+ /**
433+ * Transform skill content for Kiro.
434+ *
435+ * Minimal transform - Kiro reads standard SKILL.md format natively so we
436+ * preserve it. Only replaces PLUGIN_ROOT paths and strips namespace prefixes.
437+ *
438+ * @param {string } content - Source SKILL.md content
439+ * @param {Object } options
440+ * @param {string } options.pluginInstallPath - Absolute path to plugin install dir
441+ * @returns {string } Transformed skill content
442+ */
443+ function transformSkillForKiro ( content , options ) {
444+ const { pluginInstallPath } = options ;
445+
446+ content = content . replace ( / \$ \{ C L A U D E _ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
447+ content = content . replace ( / \$ C L A U D E _ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
448+ content = content . replace ( / \$ \{ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
449+ content = content . replace ( / \$ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
450+
451+ content = content . replace ( / (?: n e x t - t a s k | d e s l o p | s h i p | s y n c - d o c s | a u d i t - p r o j e c t | e n h a n c e | p e r f | r e p o - m a p | d r i f t - d e t e c t | c o n s u l t | d e b a t e | l e a r n | w e b - c t l ) : ( [ a - z ] [ a - z 0 - 9 - ] * ) / g, '$1' ) ;
452+
453+ return content ;
454+ }
455+
456+ /**
457+ * Transform command content for Kiro prompt files.
458+ *
459+ * Strips existing frontmatter, prepends inclusion: manual frontmatter,
460+ * replaces PLUGIN_ROOT paths, removes require()/Task() calls, strips namespaces.
461+ */
462+ function transformCommandForKiro ( content , options ) {
463+ const { pluginInstallPath, name = '' , description = '' } = options ;
464+
465+ if ( content . startsWith ( '---' ) ) {
466+ content = content . replace ( / ^ - - - \n [ \s \S ] * ?\n - - - \n ? / , '' ) ;
467+ }
468+
469+ const cleanDescription = description . replace ( / [ \x00 - \x1f \x7f ] / g, ' ' ) ;
470+ const escapedDescription = cleanDescription . replace ( / \\ / g, '\\\\' ) . replace ( / " / g, '\\"' ) ;
471+ let frontmatter = '---\n' ;
472+ frontmatter += 'inclusion: manual\n' ;
473+ if ( name ) frontmatter += `name: "${ name } "\n` ;
474+ if ( description ) frontmatter += `description: "${ escapedDescription } "\n` ;
475+ frontmatter += '---\n' ;
476+
477+ content = frontmatter + content ;
478+
479+ content = content . replace ( / \$ \{ C L A U D E _ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
480+ content = content . replace ( / \$ C L A U D E _ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
481+ content = content . replace ( / \$ \{ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
482+ content = content . replace ( / \$ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
483+
484+ content = content . replace ( / (?: c o n s t | l e t | v a r ) \s + \{ ? [ ^ } = \n ] + \} ? \s * = \s * r e q u i r e \s * \( [ ^ ) ] + \) ; ? / g, '' ) ;
485+ content = content . replace ( / r e q u i r e \s * \( [ ' " ] [ ^ ' " ] + [ ' " ] \) / g, '' ) ;
486+
487+ // Transform code blocks containing Promise.all + Task() (parallel reviewer spawns).
488+ // The bare Task() regex below can't reach inside fenced code blocks.
489+ // Fence boundaries must be at line start (^```) to avoid matching backtick
490+ // template literals inside the code as false fence endings.
491+ content = content . replace ( / ^ ` ` ` (?: j a v a s c r i p t | j s ) ? \n ( [ \s \S ] * ?) ^ ` ` ` $ / gm, ( fullBlock , codeContent ) => {
492+ if ( ! codeContent . includes ( 'Promise.all' ) || ! codeContent . includes ( 'Task(' ) ) return fullBlock ;
493+ // Use lazy [\s\S]*? for the template literal body: it stops at the first backtick and
494+ // naturally matches any character including standalone $ (e.g. $100, $BUDGET).
495+ const taskMatches = [ ...codeContent . matchAll ( / T a s k \s * \( \s * \{ [ \s \S ] * ?s u b a g e n t _ t y p e : \s * [ ' " ] (?: [ ^ " ' : ] + : ) ? ( [ ^ ' " ] + ) [ ' " ] [ \s \S ] * ?p r o m p t : \s * ` ( [ \s \S ] * ?) ` / gs) ] ;
496+ if ( taskMatches . length < 2 ) return fullBlock ;
497+
498+ const delegations = taskMatches . map ( m => {
499+ const agent = m [ 1 ] ;
500+ const promptFirstLine = m [ 2 ] . split ( '\n' ) . find ( l => l . trim ( ) ) || '' ;
501+ return `Delegate to the \`${ agent } \` subagent:\n> ${ promptFirstLine . trim ( ) } ` ;
502+ } ) ;
503+
504+ let result = delegations . join ( '\n\n' ) ;
505+
506+ const hasReviewKeyword = delegations . some ( d =>
507+ / r e v i e w | q u a l i t y | s e c u r i t y | p e r f o r m a n c e | t e s t | c o v e r a g e / i. test ( d )
508+ ) ;
509+ if ( delegations . length >= 4 && hasReviewKeyword ) {
510+ result = `**Review phase (Kiro - max 4 agents, fallback to 2 sequential):**\n\nTry delegating to these subagents (experimental parallel spawning):\n\n${ result } \n\nIf parallel spawning is unavailable, run 2 combined reviewers sequentially:\n1. Delegate to the \`reviewer-quality-security\` subagent (code quality + security)\n2. Then delegate to the \`reviewer-perf-test\` subagent (performance + test coverage)\n\nAggregate all findings from whichever execution path succeeded.` ;
511+ }
512+
513+ return result ;
514+ } ) ;
515+
516+ // Transform bare Task() calls outside code blocks
517+ content = content . replace ( / a w a i t \s + T a s k \s * \( \s * \{ [ ^ { } ] * (?: \{ [ ^ { } ] * \} [ ^ { } ] * ) * \} \s * \) ; ? / g, ( match ) => {
518+ const agentMatch = match . match ( / s u b a g e n t _ t y p e : \s * [ " ' ] (?: [ ^ " ' : ] + : ) ? ( [ ^ " ' ] + ) [ " ' ] / ) ;
519+ const promptMatch = match . match ( / p r o m p t : \s * [ ` " ' ] ( [ \s \S ] * ?) [ ` " ' ] / ) ;
520+ if ( agentMatch ) {
521+ const agentName = agentMatch [ 1 ] ;
522+ const prompt = promptMatch ? promptMatch [ 1 ] . replace ( / \\ n / g, '\n' ) . trim ( ) : '' ;
523+ if ( prompt ) {
524+ return `Delegate to the \`${ agentName } \` subagent:\n> ${ prompt . split ( '\n' ) [ 0 ] } ` ;
525+ }
526+ return `Delegate to the \`${ agentName } \` subagent.` ;
527+ }
528+ return '' ;
529+ } ) ;
530+
531+ // Transform AskUserQuestion to markdown prompt for Kiro chat
532+ content = content . replace ( / (?: a w a i t \s + ) ? A s k U s e r Q u e s t i o n \s * \( \s * \{ [ \s \S ] * ?\} \s * \) ; ? / g, ( match ) => {
533+ const questionMatch = match . match ( / q u e s t i o n : \s * [ " ' ` ] ( [ \s \S ] * ?) [ " ' ` ] / ) ;
534+ const question = questionMatch ? questionMatch [ 1 ] : 'Please choose:' ;
535+ const optionMatches = [ ...match . matchAll ( / l a b e l : \s * [ " ' ` ] ( [ ^ " ' ` ] + ) [ " ' ` ] [ \s \S ] * ?d e s c r i p t i o n : \s * [ " ' ` ] ( [ ^ " ' ` ] + ) [ " ' ` ] / g) ] ;
536+ if ( optionMatches . length > 0 ) {
537+ const options = optionMatches . map ( ( m , i ) => `${ i + 1 } . **${ m [ 1 ] } ** - ${ m [ 2 ] } ` ) . join ( '\n' ) ;
538+ return `**${ question } **\n\n${ options } \n\nReply with the number or name of your choice.` ;
539+ }
540+ return `**${ question } **\n\nReply in chat with your choice.` ;
541+ } ) ;
542+
543+ content = content . replace ( / (?: n e x t - t a s k | d e s l o p | s h i p | s y n c - d o c s | a u d i t - p r o j e c t | e n h a n c e | p e r f | r e p o - m a p | d r i f t - d e t e c t | c o n s u l t | d e b a t e | l e a r n | w e b - c t l ) : ( [ a - z ] [ a - z 0 - 9 - ] * ) / g, '$1' ) ;
544+
545+ // Batch parallel reviewer delegations for Kiro's agent limit.
546+ // Detects 4+ consecutive "Delegate to" lines with review-related names
547+ // and rewrites as try-4-then-fallback-to-2 pattern.
548+ const reviewerBatchPattern = / ( (?: D e l e g a t e t o t h e ` [ ^ ` ] * ` s u b a g e n t [ ^ \n ] * \n ) { 4 , } ) / g;
549+ content = content . replace ( reviewerBatchPattern , ( block ) => {
550+ const delegations = block . match ( / D e l e g a t e t o t h e ` ( [ ^ ` ] + ) ` s u b a g e n t / g) || [ ] ;
551+ if ( delegations . length < 4 ) return block ;
552+
553+ const hasReviewKeyword = delegations . some ( d =>
554+ / r e v i e w | q u a l i t y | s e c u r i t y | p e r f o r m a n c e | t e s t | c o v e r a g e / i. test ( d )
555+ ) ;
556+ if ( ! hasReviewKeyword ) return block ;
557+
558+ return `**Review phase (Kiro - max 4 agents, fallback to 2 sequential):**
559+
560+ Try delegating to these subagents (experimental parallel spawning):
561+ ${ block }
562+ If parallel spawning is unavailable, run 2 combined reviewers sequentially:
563+ 1. Delegate to the \`reviewer-quality-security\` subagent (code quality + security)
564+ 2. Then delegate to the \`reviewer-perf-test\` subagent (performance + test coverage)
565+
566+ Aggregate all findings from whichever execution path succeeded.\n` ;
567+ } ) ;
568+
569+ return content ;
570+ }
571+
572+ /**
573+ * Transform agent markdown+frontmatter to Kiro JSON format.
574+ *
575+ * Parses frontmatter for name/description/model/tools, uses body as prompt.
576+ * Returns a JSON string matching Kiro's agent schema.
577+ */
578+ function transformAgentForKiro ( content , options ) {
579+ const { pluginInstallPath } = options || { } ;
580+
581+ const frontmatter = discovery . parseFrontmatter ( content ) ;
582+ let body = content ;
583+ if ( content . startsWith ( '---' ) ) {
584+ const endIdx = content . indexOf ( '\n---' , 3 ) ;
585+ if ( endIdx !== - 1 ) {
586+ body = content . substring ( endIdx + 4 ) . replace ( / ^ \n / , '' ) ;
587+ }
588+ }
589+
590+ if ( pluginInstallPath ) {
591+ body = body . replace ( / \$ \{ C L A U D E _ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
592+ body = body . replace ( / \$ C L A U D E _ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
593+ body = body . replace ( / \$ \{ P L U G I N _ R O O T \} / g, ( ) => pluginInstallPath ) ;
594+ body = body . replace ( / \$ P L U G I N _ R O O T / g, ( ) => pluginInstallPath ) ;
595+ }
596+
597+ body = body . replace ( / (?: n e x t - t a s k | d e s l o p | s h i p | s y n c - d o c s | a u d i t - p r o j e c t | e n h a n c e | p e r f | r e p o - m a p | d r i f t - d e t e c t | c o n s u l t | d e b a t e | l e a r n | w e b - c t l ) : ( [ a - z ] [ a - z 0 - 9 - ] * ) / g, '$1' ) ;
598+
599+ const agent = {
600+ name : frontmatter . name || '' ,
601+ description : frontmatter . description || '' ,
602+ prompt : body . trim ( )
603+ } ;
604+
605+ if ( frontmatter . tools ) {
606+ // parseFrontmatter returns arrays for YAML list syntax, string for inline
607+ const toolItems = Array . isArray ( frontmatter . tools )
608+ ? frontmatter . tools . map ( t => t . toLowerCase ( ) )
609+ : [ frontmatter . tools . toLowerCase ( ) ] ;
610+ const toolStr = toolItems . join ( ' ' ) ;
611+ const tools = [ ] ;
612+ if ( toolStr . includes ( 'read' ) ) tools . push ( 'read' ) ;
613+ if ( toolStr . includes ( 'edit' ) || toolStr . includes ( 'write' ) ) tools . push ( 'write' ) ;
614+ if ( toolStr . includes ( 'bash' ) || toolStr . includes ( 'shell' ) ) tools . push ( 'shell' ) ;
615+ if ( toolStr . includes ( 'glob' ) ) tools . push ( 'read' ) ;
616+ if ( toolStr . includes ( 'grep' ) ) tools . push ( 'read' ) ;
617+ if ( toolStr . includes ( 'task' ) || toolStr . includes ( 'agent' ) ) tools . push ( 'shell' ) ;
618+ if ( toolStr . includes ( 'web' ) || toolStr . includes ( 'fetch' ) ) tools . push ( 'shell' ) ;
619+ if ( toolStr . includes ( 'notebook' ) ) tools . push ( 'write' ) ;
620+ if ( toolStr . includes ( 'lsp' ) ) tools . push ( 'read' ) ;
621+ const deduped = [ ...new Set ( tools ) ] ;
622+ agent . tools = deduped . length > 0 ? deduped : [ 'read' ] ;
623+ } else {
624+ agent . tools = [ 'read' ] ;
625+ }
626+
627+ agent . resources = [ 'file://.kiro/prompts/**/*.md' ] ;
628+
629+ return JSON . stringify ( agent , null , 2 ) ;
630+ }
631+
632+ /**
633+ * Generate a combined reviewer agent JSON for Kiro's 4-agent limit.
634+ * Merges multiple review responsibilities into a single agent.
635+ *
636+ * @param {Array<{name: string, focus: string}> } roles - Review passes to combine
637+ * @param {string } name - Agent name
638+ * @param {string } description - Agent description
639+ * @returns {string } JSON string for .kiro/agents/*.json
640+ */
641+ function generateCombinedReviewerAgent ( roles , name , description ) {
642+ const sections = roles . map ( r =>
643+ `## ${ r . name } Review\n\nFocus: ${ r . focus } `
644+ ) . join ( '\n\n---\n\n' ) ;
645+
646+ const agent = {
647+ name,
648+ description,
649+ prompt : `You are a combined code reviewer covering multiple review passes in a single session.\n\n${ sections } \n\nFor each file you review, check ALL of the above review dimensions. Return findings as a JSON array with objects containing: pass (which review), file, line, severity (critical/high/medium/low), description, suggestion.` ,
650+ tools : [ 'read' ] ,
651+ resources : [ 'file://.kiro/prompts/**/*.md' ] ,
652+ } ;
653+
654+ return JSON . stringify ( agent , null , 2 ) ;
655+ }
656+
300657module . exports = {
301658 transformBodyForOpenCode,
302659 transformCommandFrontmatterForOpenCode,
303660 transformAgentFrontmatterForOpenCode,
304661 transformSkillBodyForOpenCode,
305- transformForCodex
662+ transformForCodex,
663+ transformRuleForCursor,
664+ transformSkillForCursor,
665+ transformCommandForCursor,
666+ transformForCursor : transformRuleForCursor ,
667+ transformSkillForKiro,
668+ transformCommandForKiro,
669+ transformAgentForKiro,
670+ generateCombinedReviewerAgent
306671} ;
0 commit comments