App-karr
view release on metacpan or search on metacpan
measures and never resolves: nothing is fetched, and lifting `blocked`
stays `karr needs --resolve`.
- `on_drained`, the domain hook (k193): when a board has no actionable
task left, a configured command runs in it and karr does not know what
it does -- the seam that keeps karr generic (in the fleet this came
from, it drives a release gate). Its exit code is interpreted by
nobody, it never marks the agent failing, and it runs under the
board's own lock with `KARR_ROLE=hook`. A drain ending in a
common-error does not count as drained; the round in which the hook
files new work is counted and capped at `on_drained_max_rounds`, and
the same board state is never asked twice.
- `karr sync` now carries `refs/karr-foundation/*` as well as the board
(k190), since the chain, run logs and design document are coordination
state that has to reach every machine; deletions travel as tombstones
under `refs/karr-local/foundation-deleted/` with an explicit delete
refspec, never a pruning push (k178's rule), and the fleet half runs
second and never alone, behind the board's identity (k95) and
wholesale-wipe (k82) checks. Foundation also prints plain ASCII when
loaded as a module rather than run through `bin/karr-foundation`
(k214), its EXIT CODES POD no longer lumps every bad option value under
exit 2 (k217), five tests stop reading the runner's real
`~/.config/karr-foundation/config.yml` by isolating `$ENV{HOME}`
(k222), the `enable_std_utf8()` contract a direct library loader must
run is written into `App::karr::Foundation`'s POD (k221), and
`enable_std_utf8`'s own POD now names all four readers that decode
STDIN themselves (restore, set-refs, `foundation plan`, the delete
confirmation) instead of only `karr restore` (k246).
- A remote that accepts the connection and then goes silent no longer
hangs karr (k170, k174). `KARR_TRANSPORT_TIMEOUT` bounded only the
git-CLI fallback, which runs after the native call returns, so the one
path that could block was the one it could not reach; it now sets
libgit2's own network timeouts too, covering git://, http:// and
https:// (k170). ssh:// stayed unbounded there because libssh2 does
its own reads past libgit2's timeout -- fixed upstream in libgit2
1.9.3, enforced by pinning `Alien::Libgit2 0.002` (pkg-config floor
1.9.3) so a distribution libgit2 below the fix falls through to the
bundled build, with no version switch in the transport (k174).
Measured against a silent listener: 3s -> 3.11s, 8s -> 8.07s, 0 waits
as documented.
- The remote-board probe and both transports follow one policy (k203,
k204, k208). The `ls-remote` probe in front of a read now takes the
native transport first with the CLI as fallback, since the 1.9.3 floor
closed the ssh argument that had made it CLI-only, and its budget
covers both attempts (k203). `insteadOf` and `pushInsteadOf` are
applied by libgit2 itself, so `App::karr::Git`'s DESCRIPTION stops
naming `insteadOf` as CLI-only (k204). And a push whose push URL is a
local path is taken off the native transport, because libgit2's local
transport pushes to the remote's fetch URL rather than the URL it
connected to -- writing `refs/karr/*` into the wrong repository and
calling it success; the CLI fallback lands at the push URL, and the
detection is narrow enough to leave every real transport to libgit2
(k208).
- `karr sync` reports what a fetch moved correctly against libgit2 1.9,
by requiring `Git::Native 0.006`. 0.006 takes `git_fetch_options.prune`
from `Git::Libgit2::fetch_options_prune_offset` rather than a constant
derived from libgit2 1.5; against 1.9 -- where the embedded callbacks
struct is 128 bytes, not 120 -- that constant put the prune value eight
bytes early, on the `update_refs` callback pointer 1.9 prefers over
`update_tips`. `App::karr::Git::_fetch_refspecs` reads the fetch
result's `updated` list to decide what a sync moved, so a fetch that
did report ref updates was the case that misread it.
- Parallel writes and fresh clones stopped losing races (k172, k173,
k181, k182, k183). Eight `karr create` at once handed id 8 to two
cards, because a pull adopted a remote counter behind the local one;
the counter is now merged, taken only when ahead and compare-and-swapped
so an allocation in between makes the attempt re-read (k172). A per-ref
rejection from two pushes creating the same new ref is recognised as
contention and spends the existing three attempts rather than ending on
the first -- 4 to 5 of 8 creates failed against a real `git daemon`
before (k181) -- and `karr sync`, the command karr points every failed
sync at, went through the write path with no retry at all until it
shared the sync lifecycle (k183). A fresh clone reads the board instead
of being told to fetch it: a read finding nothing under `refs/karr/`
asks the remote through the bounded `ls-remote` probe and pulls it,
one line on STDERR, `KARR_NO_AUTO_FETCH=1` to switch it off (k173); and
`karr init` in such a clone asks the remote before writing, so it no
longer starts a rival board the next sync refuses as different (k182).
- A push can no longer delete a card another clone made (k178, k197).
Every push sent the board under a pruning refspec, so a card this push
did not have -- created in another clone a moment earlier -- was
deleted off the remote and then read as a remote deletion on the clone
that owned it; a push now publishes only its own refs plus one delete
refspec per ref it deleted itself, recorded as tombstones under
`refs/karr-local/deleted/` (k178). A repository with no remote settles
those tombstones rather than hoarding them, since a backlog published
to a remote added later would delete cards at those paths (k197).
- The activity log no longer rewrites itself on every entry (k171). A
log ref held one blob that `log_entry` read and wrote back per line, so
10,000 mutating commands wrote ~4.6 GB of objects for a 1 MB log,
nearly all immediately unreachable. One identity's log is now a chain
of 8 KiB segments under `refs/karr/log/<role>/<email>`, only the newest
appended to, so bytes written grow linearly and `last_entry` reads one
small ref; nothing migrates, and `karr context` asks the log which refs
are its own so a rotated segment is not misread as another agent's
activity.
- `karr set-refs` reads its payload from STDIN when no CONTENT is given,
and can no longer write the sync machinery's own refs (k189, k195,
k199). Joining arguments with a space collapsed every newline, so a
multi-line document was stored corrupted; `karr set-refs REF < file`
now stores it verbatim, an empty STDIN is refused, and at a terminal
the argument-less form stays a usage error (k195). And
`refs/karr-remote/`, `refs/karr-conflict/` (k199) and
`refs/karr-foundation/chain/`, `.../log/`, `.../questions/*` (k189)
join the blocked namespaces, since a hand-written mirror or chain entry
makes the next pull reach the wrong conclusion or the runner treat
wreckage as the plan.
- The POD and shipped docs were swept against the code (k206, k211,
k215, k216, k218, k219, k245). POD and `# ABSTRACT` lost their
non-ASCII punctuation -- 65 em dashes, ellipses, an arrow and a
multiplication sign across 12 files, guarded by a test -- because the
many interfaces that render POD do not all handle UTF-8 (k215). A pass
( run in 0.954 second using v1.01-cache-2.11-cpan-364913b4093 )