@@ -350,3 +350,117 @@ test('loop-init --help documents --with-fleet', async () => {
350350 assert . match ( stdout , / - - w i t h - f l e e t / ) ;
351351 assert . match ( stdout , / f l e e t - e n g i n e e r i n g r e g i s t r y a n d i n b o x / ) ;
352352} ) ;
353+
354+ const SCAFFOLD_PATTERNS = {
355+ 'daily-triage' : {
356+ state : 'STATE.md' ,
357+ primarySkill : 'loop-triage' ,
358+ fixCapable : false ,
359+ intake : false ,
360+ } ,
361+ 'pr-babysitter' : {
362+ state : 'pr-babysitter-state.md' ,
363+ primarySkill : 'pr-review-triage' ,
364+ fixCapable : true ,
365+ intake : false ,
366+ } ,
367+ 'ci-sweeper' : {
368+ state : 'ci-sweeper-state.md' ,
369+ primarySkill : 'ci-triage' ,
370+ fixCapable : true ,
371+ intake : false ,
372+ } ,
373+ 'dependency-sweeper' : {
374+ state : 'dependency-sweeper-state.md' ,
375+ primarySkill : 'dependency-triage' ,
376+ fixCapable : true ,
377+ intake : false ,
378+ } ,
379+ 'post-merge-cleanup' : {
380+ state : 'post-merge-state.md' ,
381+ primarySkill : 'post-merge-scan' ,
382+ fixCapable : true ,
383+ intake : false ,
384+ } ,
385+ 'changelog-drafter' : {
386+ state : 'changelog-drafter-state.md' ,
387+ primarySkill : 'changelog-scan' ,
388+ fixCapable : false ,
389+ intake : false ,
390+ } ,
391+ 'issue-triage' : {
392+ state : 'issue-triage-state.md' ,
393+ primarySkill : 'issue-triage' ,
394+ fixCapable : false ,
395+ intake : true ,
396+ } ,
397+ } ;
398+
399+ const SCAFFOLD_TOOLS = {
400+ grok : [ '.grok' , 'skills' ] ,
401+ claude : [ '.claude' , 'skills' ] ,
402+ codex : [ '.codex' , 'skills' ] ,
403+ opencode : [ 'skills' ] ,
404+ } ;
405+
406+ async function expectPathExists ( ...parts ) {
407+ await access ( path . join ( ...parts ) ) ;
408+ }
409+
410+ async function expectPathMissing ( ...parts ) {
411+ await assert . rejects ( ( ) => access ( path . join ( ...parts ) ) ) ;
412+ }
413+
414+ for ( const [ pattern , contract ] of Object . entries ( SCAFFOLD_PATTERNS ) ) {
415+ for ( const [ tool , skillRoot ] of Object . entries ( SCAFFOLD_TOOLS ) ) {
416+ test ( `loop-init scaffold matrix: ${ pattern } for ${ tool } ` , async ( ) => {
417+ const dir = await mkdtemp ( path . join ( tmpdir ( ) , `loop-init-matrix-${ pattern } -${ tool } -` ) ) ;
418+ try {
419+ const { stdout } = await exec ( 'node' , [
420+ CLI ,
421+ dir ,
422+ '--pattern' ,
423+ pattern ,
424+ '--tool' ,
425+ tool ,
426+ ] ) ;
427+
428+ assert . match ( stdout , new RegExp ( `loop-init: ${ pattern } ` ) ) ;
429+ await expectPathExists ( dir , contract . state ) ;
430+ await expectPathExists ( dir , 'AGENTS.md' ) ;
431+ await expectPathExists ( dir , 'loop-budget.md' ) ;
432+ await expectPathExists ( dir , 'loop-run-log.md' ) ;
433+ await expectPathExists ( dir , 'loop-constraints.md' ) ;
434+ await expectPathExists ( dir , ...skillRoot , contract . primarySkill , 'SKILL.md' ) ;
435+ await expectPathExists ( dir , ...skillRoot , 'loop-budget' , 'SKILL.md' ) ;
436+ await expectPathExists ( dir , ...skillRoot , 'loop-constraints' , 'SKILL.md' ) ;
437+
438+ if ( tool === 'opencode' ) {
439+ await expectPathExists ( dir , 'opencode.json' ) ;
440+ }
441+
442+ if ( contract . fixCapable ) {
443+ await expectPathExists ( dir , 'loop-ledger.json' ) ;
444+ await expectPathExists ( dir , ...skillRoot , 'minimal-fix' , 'SKILL.md' ) ;
445+ await expectPathExists ( dir , ...skillRoot , 'loop-guard' , 'SKILL.md' ) ;
446+
447+ const ledger = JSON . parse ( await readFile ( path . join ( dir , 'loop-ledger.json' ) , 'utf8' ) ) ;
448+ assert . equal ( ledger . pattern , pattern ) ;
449+ assert . match ( ledger . level , / ^ L [ 1 2 ] $ / ) ;
450+ assert . deepEqual ( ledger . attempts , [ ] ) ;
451+ } else {
452+ await expectPathMissing ( dir , 'loop-ledger.json' ) ;
453+ await expectPathMissing ( dir , ...skillRoot , 'loop-guard' , 'SKILL.md' ) ;
454+ }
455+
456+ if ( contract . intake ) {
457+ await expectPathExists ( dir , ...skillRoot , 'loop-intake' , 'SKILL.md' ) ;
458+ } else {
459+ await expectPathMissing ( dir , ...skillRoot , 'loop-intake' , 'SKILL.md' ) ;
460+ }
461+ } finally {
462+ await rm ( dir , { recursive : true , force : true } ) ;
463+ }
464+ } ) ;
465+ }
466+ }
0 commit comments