App-karr
view release on metacpan or search on metacpan
lib/App/karr/Cmd/Handoff.pm view on Meta::CPAN
->handoff_status;
# Handoff used to read the task, mutate it and save it back unguarded, so a
# claim landing in that window was overwritten rather than obeyed -- the same
# read-then-write #44/#46/#56 closed everywhere else. update_task_guarded is
# that closure: the claim rule below is applied to the revision this writes,
# and re-applied if another agent gets in first (ticket #97).
my $task = $self->update_task_guarded($id, sub {
my ($task) = @_;
# The one claim-ownership rule, shared with move/edit/delete/archive rather
# than reimplemented here.
$self->check_claim($task, $self->claim);
# And the one status-change path, so the handoff obeys the same
# require_claim, status validation and lifecycle stamps as `karr move`
# (tickets #54, #55, #68). --claim is required on this command, so a target
# status flagged require_claim is always satisfied.
$self->apply_status_change($task, $target, $self->claim);
# Refresh claim
$task->claimed_by($self->claim);
$task->claimed_at(gmtime->datetime . 'Z');
# Block if requested. length, not truth: --block 0 is a reason (ticket #153,
# extending ticket #78's rule to the handoff path).
if (defined $self->block && length $self->block) {
$task->block($self->block);
}
# Append note. length, not truth: --note 0 is a note (ticket #153, the
# same fix as --append_body in edit).
if (defined $self->note && length $self->note) {
my $note_text = $self->note;
if ($self->timestamp) {
$note_text = gmtime->strftime('%Y-%m-%d %H:%M') . ' ' . $note_text;
}
my $have = defined $task->body && length $task->body;
$task->body(($have ? $task->body . "\n" : '') . $note_text);
}
# Release claim if requested
if ($self->release) {
$task->clear_claimed_by;
$task->clear_claimed_at;
}
});
$self->sync_after;
# The handoff target is a working column, so apply_status_change above will
# have recorded any unsatisfied dependencies; this emits them (ticket #123).
my %dependency = $self->dependency_report( $task->id );
if ($self->json) {
$self->print_json({ %{ $task->to_json_hash }, %dependency });
return;
}
my $msg = sprintf "Handed off task %d -> %s", $task->id, $target;
$msg .= sprintf " (blocked: %s)", $self->block if $self->block;
$msg .= " (claim released)" if $self->release;
print "$msg\n";
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
App::karr::Cmd::Handoff - Hand off a task for review
=head1 VERSION
version 0.500
=head1 SYNOPSIS
karr handoff 7 --claim agent-fox
karr handoff 7 --claim agent-fox --note "Implementation complete" --timestamp
karr handoff 7 --claim agent-fox --block "waiting for QA" --release
=head1 DESCRIPTION
Moves a task into the board's review column -- C<review> where the board
configures one, the last non-terminal column where it does not
(L<App::karr::Config/handoff_status>) -- and refreshes its claim so the next
stage of work can see who handed it off. The command can append a note, add a
blocker, and optionally release the claim after the handoff.
=head1 OPTIONS
=over 4
=item * C<--claim>
Required. Identifies the agent performing the handoff and is validated against
the current claim unless that claim has expired.
=item * C<--note>, C<--timestamp>
Append handoff text to the task body, optionally prefixed with the current UTC
timestamp.
=item * C<--block>, C<--release>
Record a blocking reason and/or clear the claim immediately after the handoff.
=back
=head1 SEE ALSO
L<karr>, L<App::karr>, L<App::karr::Cmd::Pick>, L<App::karr::Cmd::Move>,
L<App::karr::Cmd::Edit>, L<App::karr::Cmd::Log>
=head1 SUPPORT
( run in 0.642 second using v1.01-cache-2.11-cpan-788537b7465 )