0.301     2026-06-04 22:35:33Z

    - karr-foundation: stream agent output to the terminal when interactive
      (TTY detected) or --verbose is set. The parent process now reads the
      child's output through a native pipe and fans it to the log, the
      terminal, and an in-memory buffer — no external `tee` and no re-reading
      the log by byte offset. The per-run timeout is `select`-based (robust
      against Perl's deferred signals) and only fires when max_runtime > 0
      (max_runtime: 0 disables it entirely). Output is always appended to
      .karr.log regardless of TTY.
    - karr-foundation is now a multi-board coordinator, not just an agent
      runner. Agent execution is opt-in: with no agent configured on any
      board, the default action is a read-only overview of every board
      (status counts, in-progress/blocked, lock/cooldown state). `--status`
      forces that overview regardless of configuration.
    - karr-foundation: `claude: true` synthesizes the canonical claude
      invocation so you needn't retype it; `claude_bin`, `claude_max_turns`
      and `claude_permission_mode` override the parts. The agent instruction
      is exposed as the `$PROMPT` substitution variable (settable via `prompt`
      in .karr or `default_prompt` in config), usable in any command template.
    - Activity log entries are now keyed by a role-qualified identity
      (`refs/karr/log/<role>/<email>`, role `user` or `agent`) so a human and
      an AI sharing one Git config are told apart. The role propagates to
      nested karr calls via the KARR_ROLE env var (foundation sets `agent`);
      pre-existing bare-email logs are still read for the `user` role.
    - karr show: with no ID shows the single most recently updated task;
      `--last N` widens that, `--me` shows the task(s) the current identity
      most recently acted on (via the activity log), and `--agent NAME` shows
      the task(s) most recently claimed by that agent name.
    - karr board: hide the `@claimed_by` badge and claimed-count for tasks in
      a terminal status (done/archived) — a claim is an active lease, and the
      history remains in the activity log.
    - sync: surface the real libgit2 error on a failed pull/push instead of a
      meaningless "(exit code $?)" (native libgit2 operations have no shell
      exit code). New Git `last_error` accessor records the last remote-op
      exception.

0.300     2026-05-27 20:43:23Z

    - Docker: bundle libgit2 (Alien::Libgit2 share build) so the runtime
      image is self-contained. Builder installs cmake/pkg-config/zlib/
      libssh2 dev headers and sets ALIEN_INSTALL_TYPE=share; runtime-base
      installs libssl3/libssh2-1/zlib1g (the shared libs the vendored
      libgit2.so links against). Needed since Git::Native moved to
      Git::Libgit2 (libgit2 FFI).
    - Add .github/workflows/ci.yml (perl 5.36/5.38/5.40) using the
      [@Author::GETTY] dzil-test composite action; installs libgit2-dev so
      Alien::Libgit2 links the system libgit2 (>= 1.5) in CI.
    - Git.pm: read git config (user.name/email) and validate helper ref
      names through Git::Native (Config + reference_name_is_valid) instead
      of poking Git::Libgit2::FFI directly. New Git.pm `ref_oids` helper.
    - karr-foundation: detect board changes via Git::Native instead of
      shelling out to `git for-each-ref` — no git binary needed for that
      path anymore. Sync (`--pull`) and open-task detection now run
      in-process via App::karr::Git/BoardStore instead of forking the
      `karr` CLI.
    - karr-foundation: drain each board instead of a single run — invoke
      the agent command repeatedly until no actionable task (non-terminal
      and unblocked) remains. A task the agent claims but never moves is
      auto-blocked after `max_attempts` stalls (default 2) so the drain
      always terminates; the agent's own `--block` reason still wins.
      Observable common errors (non-zero/timeout exit, or a log match
      against rate-limit/auth/network/5xx patterns, extensible via
      `error_patterns`) never penalize a task and instead trigger an
      exponential per-repo cooldown (1, 2, 4, … minutes, capped). New
      `.karr` keys: `drain`, `max_attempts`, `max_iterations`,
      `cooldown_base`, `cooldown_max`, `error_patterns`.
    - cpanfile: require Git::Native 0.003 and Git::Libgit2 0.004.
    - Fix `karr context` / `karr context --json` crashing with
      "Can't locate object method 'strftime' via package 'Sun May ...'":
      Cmd::Context now `use Time::Piece`, so `gmtime` returns a
      Time::Piece object instead of a plain string. Added t/07-context.t
      covering the plain, --json, and recently-completed cutoff paths.
    - Fix `karr config show` (and get/set) crashing with
      "Can't locate object method 'board_dir'": Cmd::Config now builds
      its config via `$self->store->effective_config` and persists with
      `$self->store->save_config`, instead of calling the non-existent
      `board_dir` on itself. Added t/06-config-cmd.t.
    - Drop hard-coded `tags = latest` / `tags = user` in the Docker
      subsections so the new `[@Author::GETTY::Docker]` default
      (`latest %V %v`) applies. `runtime-user` keeps a `-user`
      suffix on each tag.
    - Add `karr-foundation` binary and `App::karr::Foundation` module:
      single-shot daemon for periodic agent execution across multiple karr
      boards. Reads `~/.config/karr-foundation/config.yml` (dirs: / scan:),
      checks each repo for board changes or open tasks, and invokes the
      per-repo `.karr` command. Supports `--force`, `--dry-run`, `--verbose`.
      Per-repo state in `.karr.state` / `.karr.lock` / `.karr.log` (gitignored).

0.202     2026-05-17 05:17:07Z

    - Fix `karr list` crashing with "Can't locate object method 'load_tasks'":
      Cmd::List was missing `with 'App::karr::Role::BoardAccess'` (the role was
      `use`d but never consumed). Surfaced while writing worktree tests.
    - Add t/29-worktree.t covering init/create/list inside `git worktree`
      directories and verifying refs/karr/* are correctly shared between the
      main work-tree and additional worktrees.

0.200     2026-05-16 17:45:23Z

    - Centralize config knowledge: priority_order(), class_order(),
      terminal_statuses(), is_terminal_status(), status_requires_claim()
      moved to Config and BoardStore (no more duplication across commands).
    - Add all_status_names(), status_requires_claim(), is_terminal_status()
      to BoardStore for encapsulated status config access.
    - Convert all require Time::Piece to use Time::Piece (Pick, Move, Edit).
    - Extract append_log into App::karr::ActivityLog module.
    - Architecture refactor: split Role::BoardAccess into Role::BoardDiscovery +
      Role::SyncLifecycle. Commands now work directly on refs via BoardStore
      instead of via a materialized temp directory.
    - Add SyncGuard (push insurance on die/croak), effective_config() on BoardStore,
      and $self->config via Role::BoardDiscovery.
    - Add tasks/ to .gitignore (never commit materialized view).
    - Fix CPAN smoker failures: skip git tests on old git (< 1.8.5, no -C flag)
    - Fix skip() without SKIP block in t/11-git-impl.t (Test::More crash)
    - Skip user.email test gracefully when not configured

0.101     2026-03-23 03:02:05Z

    - Strengthen docs and GitHub landing pages
    - Add POD to all modules (bin/karr, BoardStore, commands, roles)

0.100     2026-03-23 01:50:27Z

    - Migrate board state to git refs only (refs/karr/*), drop karr/ directory
    - Add backup and restore commands for refs/karr snapshot export/import
    - Add destroy command (remove all board refs, local and remote)
    - Add set-refs / get-refs helper commands for arbitrary ref storage
    - Add skill command with File::ShareDir-based skill loading
    - Simplify board output and drop WIP limits from config
    - Split Docker runtime images (slim + full) with entrypoint script
    - Expand POD across Git.pm, Lock.pm, commands, and roles

0.003     2026-03-20 05:01:01Z

    - BREAKING: Git sync stores task data in commit-wrapped refs (pushable/fetchable)
    - Full board sync via refs/karr/* (fetch/materialize/serialize/push)
    - Add karr log command for activity trail (per-agent NDJSON refs)
    - Add --claimed-by filter to list command
    - Add Task->from_string for ref-based loading
    - Rewrite Git.pm with safe execution (_git_cmd, no shell injection)
    - Fix write_ref to create commit-wrapped refs (blob→tree→commit)
    - Fix is_repo to work from subdirectories (git rev-parse)
    - Fix push refspec to refs/karr/*:refs/karr/*
    - Pick command uses Lock for atomic task claiming
    - Remove .gitignore manipulation from init
    - Extract sync_before/sync_after into BoardAccess role
    - Extract _parse_timeout/_claim_expired into ClaimTimeout role
    - Refactor Lock.pm to accept pre-built Git object
    - Docker: add default git identity ENV vars
    - Add karr sync command (--push, --pull)
    - Add auto-sync to write commands (create, move, edit, delete, pick, handoff, archive)
    - Add App::karr::Git for Git operations via CLI
    - Add App::karr::Lock for task locking via refs/karr/tasks/<id>/lock
    - Add Docker support (raudssus/karr on GHCR)
    - Initial release
    - Implemented archive command (soft-delete to archived status)
    - Implemented handoff command (move to review with claim, note, block/release)
    - Implemented config command (show/get/set board configuration)
    - Implemented context command (generate markdown board summary for embedding)
    - Implemented agent-name command (random two-word name generator)
    - Implemented skill command (install/check/update/show agent skills)
    - Added batch operations (comma-separated IDs) to move, edit, delete, archive
    - Added --json output to all commands (show, move, edit, delete, archive, handoff, board, pick)
    - Added --compact output to board command
    - Renamed all Command packages to CamelCase
    - Moved shared helpers (find_task, load_tasks, parse_ids) into BoardAccess role
    - Added --claude-skill flag to init for installing Claude Code skill
    - Ships skill via File::ShareDir (share/claude-skill.md)
    - Extracted --json and --compact into App::karr::Role::Output
