NAME
App::karr::Role::BoardDiscovery - Role providing minimal board discovery and config access
VERSION
version 0.500
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 fromgit_root— path to the Git repository (walks up fromdiror CWD)store— App::karr::BoardStore instance backed by the Git repogit— shortcut to$self->store->git(lazy)config— shortcut to$self->store->effective_config(lazy)
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. Run 'karr init' to create one.", the sentencebackup,destroy,materializeandrepairraise off "has_board_refs" in App::karr::BoardStore for the same state;refs present,
refs/karr/configmissing — a half-board: the message names it as one, says how many task refs are at stake, and says thatkarr initcompletes 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/— refuse. Namingrefs/karr/says what was looked at, and where the repository has a remote the message leads withkarr sync, notkarr init: on a fresh clone the board exists and is merely unfetched, andinitis the one command that would answer that by starting a second, empty one.refs present,
refs/karr/configmissing — 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--jsonparsable.
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; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.