NAME

App::karr::Role::BoardDiscovery - Role providing minimal board discovery and config access

VERSION

version 0.600

DESCRIPTION

This role provides the minimal interface for discovering the board's Git repository and BoardStore. It provides:

  • dir -- CLI option overriding the directory discovery starts from

  • git_root -- path to the Git repository (walks up from dir or CWD)

  • store -- App::karr::BoardStore instance backed by the Git repo

  • git -- shortcut to $self->store->git (lazy)

  • config -- shortcut to $self->store->effective_config (lazy)

  • role -- activity log identity role, user (default) or agent; read from KARR_ROLE when not overridden

Commands that need the sync lifecycle should also compose App::karr::Role::SyncLifecycle.

require_board

$self->sync_before;
$self->require_board;

Refuses to go on when this repository has no initialized board. Every command that writes to refs/karr/* calls it, because without the check a karr create typed in the wrong directory silently seeded a partial board in an unrelated repository -- and that partial board then locked karr init out of it permanently (#62).

It distinguishes the two ways of not having a board, because they call for different things from the reader (#133):

  • nothing under refs/karr/ -- "No karr board found:", followed by karr init on its own line ("command_hint" in App::karr::Error), the same message backup, destroy, materialize and repair raise off "has_board_refs" in App::karr::BoardStore for the same state;

  • refs present, refs/karr/config missing -- a half-board: the message names it as one, says how many task refs are at stake, and says that karr init completes it without discarding them.

Call it after sync_before, never before: on a fresh clone the board only exists on the remote until the pull has run, and checking first would report a board that is merely not fetched yet as missing. The four commands that read or clean up raw refs (backup, destroy, materialize, repair) ask "has_board_refs" in App::karr::BoardStore instead, so they can still deal with a half-board left behind by an older karr.

The read-only commands do not sync, so they cannot use this method; they ask "require_local_board", which puts karr sync in front of karr init for exactly the fresh clone this one may assume has already been pulled.

require_local_board

$self->require_local_board;   # no sync_before: reads stay offline
$self->require_local_board( hint => "...one more sentence.\n" );

The read side of "require_board", for the commands that render the board without pulling first (board, list, show, log, context, and config show/config get). It answers one question those commands never asked: was anything actually read here? Without it they rendered the code defaults over an empty task list, so a repository holding no board printed exactly what a board holding no tasks prints -- and since git clone does not fetch refs/karr/*, that is the normal state of every fresh clone, where the user's tickets are all on the remote (#135, and #136 for the config half).

The two states "require_board" distinguishes need different answers on the read path:

  • nothing under refs/karr/ -- fetch it, if there is anything to fetch; otherwise refuse. Where the repository has a remote and that remote advertises refs/karr/*, the board is not missing, it is merely unfetched, and karr can see that from where it stands, so it pulls once and answers the question that was asked (#173). One line on STDERR says it did; KARR_NO_AUTO_FETCH=1 switches it off for good, in an environment where karr may not touch the network. The refusal stays for the case where it is the truth -- no remote, or a remote with no board -- and where there is a remote it still leads with karr sync rather than karr init, which is the one command that would answer an unfetched board by starting a second, empty one.

  • refs present, refs/karr/config missing -- a half-board: go on, and say so on STDERR. Refusing would hide tasks that are demonstrably there, which is the mistake #133 was about; but the board name, statuses and defaults being rendered are karr's own, not the board's, and nothing else on the page says so. STDERR keeps --json parsable.

Reads deliberately do not sync (a network round trip in front of every karr show is not worth it, and a stale read is recoverable where a stale write is not), so unlike "require_board" this may be called first thing in execute -- after option validation, so that a usage error still exits 2.

The optional hint argument appends one caller-supplied sentence to the refusal, for a command that can offer something beyond karr sync / karr init. App::karr::Cmd::Config is the one caller: what it used to print here -- karr's built-in defaults -- is a real answer to a different question, so its refusal points at karr config show --defaults, where the same values are true by construction (#136). The half-board note takes no hint: it already says the values shown are karr's own.

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, licensed under:

The Artistic License 2.0 (GPL Compatible)