App-karr
view release on metacpan or search on metacpan
t/34-foundation-command.t view on Meta::CPAN
use strict;
use warnings;
use Test::More;
use lib 't/lib';
use TestGit qw( require_git_c );
require_git_c();
use File::Temp qw( tempdir );
use Path::Tiny qw( path );
use YAML::XS qw( Dump );
use App::karr::Git;
use App::karr::Task;
use App::karr::Foundation;
my $repo = path( tempdir( CLEANUP => 1 ) );
subtest '_agent_command resolution precedence' => sub {
my $f = App::karr::Foundation->new( _config_data => {} );
is $f->_agent_command( $repo, {} ), undef,
'no agent configured -> undef';
is $f->_agent_command( $repo, { command => 'foo' } ), 'foo',
'.karr command used';
is $f->_agent_command( $repo, { command => 'foo', claude => 1 } ), 'foo',
'explicit command wins over claude: true';
is $f->_agent_command( $repo, { claude => 1 } ),
'claude -p "$PROMPT" --permission-mode bypassPermissions --max-turns 30',
'claude: true synthesizes the canonical command';
is $f->_agent_command( $repo,
{ claude => 1, claude_bin => 'claude_with_minimax', claude_max_turns => 5, claude_permission_mode => 'plan' } ),
'claude_with_minimax -p "$PROMPT" --permission-mode plan --max-turns 5',
'claude_bin and knobs override the defaults';
};
subtest 'config-level defaults and CLI override' => sub {
my $fd = App::karr::Foundation->new( _config_data => { default_command => 'gd' } );
is $fd->_agent_command( $repo, { command => 'foo' } ), 'gd',
'config default_command beats .karr command';
my $fc = App::karr::Foundation->new( command => 'cli', _config_data => { default_command => 'gd' } );
is $fc->_agent_command( $repo, { command => 'foo' } ), 'cli',
'CLI --command wins over everything';
my $fg = App::karr::Foundation->new( _config_data => { claude => 1 } );
like $fg->_agent_command( $repo, {} ), qr/^claude -p "\$PROMPT"/,
'global claude: true applies when no per-repo agent';
};
subtest '_prompt_for precedence' => sub {
my $f = App::karr::Foundation->new( _config_data => { default_prompt => 'CFG' } );
is $f->_prompt_for( { prompt => 'KARR' } ), 'KARR', '.karr prompt wins';
is $f->_prompt_for( {} ), 'CFG', 'config default_prompt next';
my $f2 = App::karr::Foundation->new( _config_data => {} );
like $f2->_prompt_for( {} ), qr/karr-coordinator skill/, 'built-in default last';
};
subtest '$PROMPT is substituted into the command at run time' => sub {
my $rdir = path( tempdir( CLEANUP => 1 ) );
my $f = App::karr::Foundation->new( _config_data => {} );
my ( $code, $out ) = $f->_run_command( $rdir, {}, 'printf "%s" "$PROMPT"' );
like $out, qr/karr-coordinator skill/, 'default prompt reaches $PROMPT';
my ( $c2, $o2 ) = $f->_run_command( $rdir, { prompt => 'CUSTOM-PROMPT' }, 'printf "%s" "$PROMPT"' );
is $o2, 'CUSTOM-PROMPT', 'per-repo prompt overrides';
};
subtest '_print_overview renders a board summary' => sub {
my $rdir = path( tempdir( CLEANUP => 1 ) );
system( 'git', 'init', '-q', "$rdir" );
system( 'git', '-C', "$rdir", 'config', 'user.email', 'o@test.com' );
system( 'git', '-C', "$rdir", 'config', 'user.name', 'O' );
my $git = App::karr::Git->new( dir => "$rdir" );
$git->write_ref( 'refs/karr/config', Dump( { version => 1 } ) );
$git->write_ref( 'refs/karr/meta/next-id', "3\n" );
require App::karr::BoardStore;
my $store = App::karr::BoardStore->new( git => $git );
$store->save_task( App::karr::Task->new( id => 1, title => 'A', status => 'in-progress', priority => 'medium', class => 'standard' ) );
$store->save_task( App::karr::Task->new( id => 2, title => 'B', status => 'todo', priority => 'medium', class => 'standard' ) );
my $f = App::karr::Foundation->new( _config_data => {} );
my $out = '';
{
local *STDOUT;
open STDOUT, '>', \$out or die $!;
$f->_print_overview( [$rdir] );
}
like $out, qr/\Q@{[ $rdir->basename ]}\E/, 'board name shown';
like $out, qr/2 tasks/, 'task total shown';
like $out, qr/in-progress:1/, 'status counts shown';
like $out, qr/in-progress: #1/, 'in-progress ids listed';
};
done_testing;
( run in 1.184 second using v1.01-cache-2.11-cpan-0b5f733616e )