App-karr

 view release on metacpan or  search on metacpan

lib/App/karr.pm  view on Meta::CPAN

  [ skill     => 'Install/update agent skills' ],
  [ 'set-refs' => 'Store helper payloads in a Git ref' ],
  [ 'get-refs' => 'Fetch and print helper payloads from a Git ref' ],
);

sub _print_help {
  my ($self_or_class, $code) = @_;
  $code //= 0;

  my $out = '';
  $out .= colored("karr", 'bold') . " - Kanban Assignment & Responsibility Registry\n\n";
  $out .= colored("USAGE:", 'bold') . " karr [--dir PATH] <command> [options]\n\n";
  $out .= colored("COMMANDS:", 'bold') . "\n";

  my $max = 0;
  for (@COMMANDS) { $max = length($_->[0]) if length($_->[0]) > $max }

  for my $cmd (@COMMANDS) {
    $out .= sprintf "  %-*s  %s\n", $max, colored($cmd->[0], 'cyan'), $cmd->[1];
  }

  $out .= "\n" . colored("OPTIONS:", 'bold') . "\n";
  $out .= "  --dir PATH   Starting path for Git repository discovery\n";
  $out .= "  --json       JSON output (most commands)\n";
  $out .= "  --compact    Compact output (list, board)\n";
  $out .= "\n" . colored("EXAMPLES:", 'bold') . "\n";
  $out .= "  karr init --name \"My Project\"\n";
  $out .= "  karr create --title \"Fix login bug\" --priority high\n";
  $out .= "  karr list --status todo,in-progress\n";
  $out .= "  karr move 1 in-progress --claim agent-fox\n";
  $out .= "  karr pick --claim agent-fox --move in-progress\n";
  $out .= "  karr backup > karr-backup.yml\n";
  $out .= "  karr restore --yes < karr-backup.yml\n";
  $out .= "  karr set-refs superpowers/spec/1234.md draft ready\n";
  $out .= "  karr board\n";
  $out .= "\nRun " . colored("karr <command> --help", 'bold') . " for command-specific options.\n";

  if ($code > 0) { warn $out } else { print $out }
  exit $code if $code >= 0;
}

around options_usage      => sub { $_[1]->_print_help($_[2]) };
around options_help       => sub { $_[1]->_print_help($_[2]) };
around options_short_usage => sub { $_[1]->_print_help($_[2]) };

sub execute {

lib/App/karr/Cmd/Board.pm  view on Meta::CPAN

my %STATUS_STYLE = (
  backlog       => 'black on_bright_white',
  todo          => 'black on_cyan',
  'in-progress' => 'black on_yellow',
  review        => 'black on_bright_white',
  done          => 'black on_green',
  archived      => 'white on_black',
);

my %PRIORITY_COLOR = (
  critical => 'bold red',
  high     => 'red',
  medium   => 'yellow',
  low      => 'black',
);

sub execute {
  my ($self, $args_ref, $chain_ref) = @_;

  my $ec = $self->store->effective_config;
  my @statuses = $self->store->all_status_names;

lib/App/karr/Cmd/Board.pm  view on Meta::CPAN

    for my $status (@statuses) {
      my $tasks_in_status = $by_status{$status} // [];
      my $count = scalar @$tasks_in_status;
      my $ids = join(',', map { $_->id } @$tasks_in_status);
      printf "%s(%d): %s\n", $status, $count, $ids || '-';
    }
    return;
  }

  my $board_name = $ec->{board}{name} // 'Kanban Board';
  my $title = colored(" $board_name ", 'bold cyan on_black');
  print "\n $title\n\n";

  # Skip empty archived unless it has tasks
  my @display_statuses = grep {
    $_ ne 'archived' || @{$by_status{$_} // []}
  } @statuses;

  my $has_tasks = 0;
  for my $status (@display_statuses) {
    my $tasks = $by_status{$status} // [];
    my $count = scalar @$tasks;
    my $style = $STATUS_STYLE{$status} // 'white on_black';

    my $header = uc($status);
    printf " %s %s\n", colored(" $header ", $style), "[$count]";

    if (@$tasks) {
      $has_tasks = 1;
      print " " . ('-' x 52) . "\n";
      for my $t (@$tasks) {
        my $id_str = colored(sprintf('#%d', $t->id), 'bold');
        my $pri_color = $PRIORITY_COLOR{$t->priority} // 'white';
        my $pri_str = colored($t->priority, $pri_color);
        my $title = $t->title;

        my @badges;
        if ($t->has_claimed_by && $t->status ne 'done' && $t->status ne 'archived') {
          push @badges, colored('@' . $t->claimed_by, 'cyan');
        }
        if ($t->has_blocked) {
          push @badges, colored('BLOCKED', 'bold red');
        }
        if ($t->has_due) {
          push @badges, colored('due:' . $t->due, 'yellow');
        }

        printf "   %s  %-8s  %s", $id_str, $pri_str, $title;
        printf "  %s", join(' ', @badges) if @badges;
        print "\n";
      }
    }
    print "\n";
  }

  # Summary line
  my $blocked = grep { $_->has_blocked } @tasks;
  my $claimed = grep { $_->has_claimed_by && $_->status ne 'done' && $_->status ne 'archived' } @tasks;
  my @summary;
  push @summary, colored(scalar(@tasks) . ' tasks', 'bold');
  push @summary, colored("$claimed claimed", 'cyan') if $claimed;
  push @summary, colored("$blocked blocked", 'red') if $blocked;
  printf " %s\n\n", join('  ', @summary);
}

1;

__END__

=pod



( run in 0.433 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )