NAME

App::karr::ActivityLog - Activity log writer for karr board operations

VERSION

version 0.500

SYNOPSIS

use App::karr::ActivityLog;
use App::karr::Git;

my $git = App::karr::Git->new(dir => '.');
my $log = App::karr::ActivityLog->new(git => $git, role => 'agent');

$log->log_entry(
    agent   => 'agent-fox',
    action  => 'pick',
    task_id => 5,
    detail  => 'in-progress',
);

DESCRIPTION

Writes append-style JSON log entries to refs/karr/log/<identity> refs. Each entry receives an automatic timestamp if not provided.

The identity is <role>/<email>: the Git user email percent-encoded into a ref name and qualified by a role (user or agent). The role disambiguates a human and an AI agent that share one Git config. It defaults to the KARR_ROLE environment variable, or user.

Identity encoding

Git's ref-name grammar is far narrower than what a mail address may contain, so each component is percent-encoded ("identity", "decode_identity"). [A-Za-z0-9._-] survives literally to keep the common address readable; every other octet becomes %XX, including % itself, which makes the mapping injective -- two different addresses can no longer land on one ref.

Older karr releases replaced every unsafe character with _, which both collided (a b@x and a-b@x shared a ref) and produced names git rejects (a..b@x, x@y.lock). Refs written that way are not rewritten: "entries" reads them alongside the current one so existing history stays visible.

METHODS

role

The actor role, user (default) or agent. Read from KARR_ROLE when not given explicitly.

identity

my $id = $log->identity;   # e.g. "agent/getty%40conflict.industries"

The percent-encoded <role>/<email> string keying this actor's log. Always a legal pair of git ref components; see "decode_identity" for the inverse.

decode_identity

my ($role, $email) = App::karr::ActivityLog->decode_identity($id);

Turns an encoded identity -- the part of a refs/karr/log/* ref name below refs/karr/log/ -- back into the role and mail address it was built from.

log_entry

$log->log_entry(
    agent   => 'agent-fox',
    action  => 'pick',
    task_id => 5,
    detail  => 'in-progress',
    ts      => '2026-05-15T10:00:00Z',  # optional, auto-generated
);

Writes a JSON log line to the per-identity ref. The ref path is refs/karr/log/<role>/<encoded_email>.

Returns the result of "write_ref" in Git, or 0 after warning if the entry could not be written. It never dies: by the time a command logs, it has already written the task the entry describes, so a failure here must not take the command down with a half-applied mutation behind it (#75).

entries

my @entries = $log->entries;

Returns the decoded log entries for this identity, oldest first. Refs written under the pre-#75 naming schemes are read first and merged in ahead of the current ref, which is also their chronological order: a board stops being written under an old scheme the moment it is touched by a karr that knows the new one.

last_entry

my $entry = $log->last_entry;

The most recent decoded log entry for this identity, or undef if none.

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/karr/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.