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.