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 from

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

  • storeApp::karr::BoardStore instance backed by the Git repo

  • git — 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 sentence 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/ — refuse. Naming refs/karr/ says what was looked at, and where the repository has a remote the message leads with karr sync, not karr init: on a fresh clone the board exists and is merely unfetched, and init is the one command that would answer that 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; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.