balls 0.5.12

Git-native task tracker for parallel agent workflows
Documentation
# The hook schedule (§6) — the seeded default a fresh landing starts from.
#
# `[hooks]` is the SINGLE source of truth for plugin wiring: each `<op>.<phase>`
# key maps to an ordered list of plugin names. Listed = run this plugin in this
# op-phase; list position = run order (the last name runs last). An absent key or
# empty list = run nothing. The names are pure text and travel verbatim on `bl
# install`; the local `config/plugins/bin/<name>` symlink (gitignored) resolves
# each name to this box's binary.
#
# This default wires the two shipped capabilities — `bl-tracker` (remote sync) and
# `bl-delivery` (the code worktree). `bl prime` PRUNES any entry whose binary is
# not installed beside `bl`, so a tracker-less or test box never aborts. Replace
# this file (or the whole `$XDG_CONFIG_HOME/balls/default-config/` folder) to
# ship an org's own default capability set without touching core (§1/§12).
#
# WHICH HOOKS CARRY `bl-tracker` IS THE PUBLICATION POLICY (bl-3616 §3/§6 Q6).
# balls picks no default beyond this file — the ladder is the schedule, and moving
# between rungs is a `bl conf` edit, never a mode, a field, or a flag:
#
#   (a) MANDATORY replication — this seed: the tracker on every mutating `*.post`,
#       so each seal publishes as the op lands (a non-ff reject reconciles once —
#       rebase onto the remote tip, push again — and only a same-ball race aborts).
#   (b) OPT-IN publication — tracker on `sync.pre` / `prime.*` / `install.pre`
#       only: `bl conf remove <op>.post bl-tracker` for create/update/claim/
#       unclaim/close/import. Seals stay local until `bl sync` (which IS the
#       reconcile + push); `bl list`'s header and `bl show`'s `published` line
#       keep saying how far ahead you are.
#   (c) OCCUPANCY-EAGER — keep the tracker on `claim.post` + `unclaim.post`, drop
#       it from `create/update/close.post`: claims publish now (two boxes never
#       claim one ball unknowingly), content publishes at `bl sync`.
#
# Identity shims ride the same seam: `--as ID` is the one identity injection
# point (every seal carries a `bl-actor` trailer), and a plugin that publishes
# upward may rewrite or qualify it (`mark/Inflate` on a shared store, `Inflate`
# here) as ITS config — the agent→user relation is a plugin's rendering of the
# trailer, never a field on the ball.

[hooks]
"sync.pre"     = ["bl-tracker"]                  # import remote state first
"prime.pre"    = ["bl-tracker"]
"install.pre"  = ["bl-tracker"]                  # fetch the center's config to adopt (§13 prime --install)
"prime.post"   = ["bl-delivery", "bl-tracker"]   # backstop prune of settled work/<id> branches (worktrees materialize at claim only), then settle store content (fetch-ff + push)
"claim.post"   = ["bl-delivery", "bl-tracker"]   # worktree (prints its path), then the push (tracker last)
"unclaim.post" = ["bl-delivery", "bl-tracker"]
"show"         = ["bl-delivery", "bl-tracker"]  # read-op (§6, single phase): fold the worktree path (§11) + the ball's `published` drift line (§13) into the human render
"list"         = ["bl-tracker"]                  # read-op: the store-level `store: N ahead, M behind` header (§13)
"close.pre"    = ["bl-delivery"]              # deliver (squash) before the seal
"close.post"   = ["bl-delivery", "bl-tracker"]   # teardown (worktree + the work/<id> branch), then push
"create.post"  = ["bl-tracker"]
"update.post"  = ["bl-tracker"]
"import.post"  = ["bl-tracker"]                  # imported records sync like any mutate (§16)