tracker #
tracker is the pure state model for a Git-native issue tracker. A row carries
its acceptance checks and, while owned, the holder and instant of its claim.
The durable store is a dedicated tracker Git repository, independent of the
code repositories it describes. Creating a code branch does not fork issue
state or claims; only the designated tracker store ref accepts them.
Tracker.Core.claim and Tracker.Core.release return a new row or a refusal;
the caller persists the result only after checking that the store still has
the row it read. No claim expires with time.
A claim's holder is a name the writer gives; tracker keeps no roster of
writers and no rule about who may release whose claim. Who wrote a change is
Git's answer, the commit's author, and who may write the store is whoever may
push to its remote. Tracker.Core.release ~holder removes a claim only if
holder still holds it, a compare-and-swap on the holder.
The core is independent of Git and IO. Row.v creates an open row with
an explicit filing instant, priority, triage state, acceptance checks, labels
and typed edges. A caller that needs to inspect a claim can use Row.claim,
which returns the holder and timestamp when one exists. Row.claim_holder is for a
row known to be claimed and raises on an unclaimed row.
Schema.snapshot checks row kinds, statuses, label families, check kinds and unique
row IDs before admitting a set of rows. Schema.rewrite validates every row
against a replacement vocabulary while preserving row identity.
Row.merge ~ancestor left right combines independent label, check and edge
changes with the vendored mrdt three-way set merge. Competing scalar changes
are conflicts; a claim or status change must go through the authority.
Row_json.of_string ~schema ~id reads a stored row.json against the schema
from its Git tree. The id comes from the row directory. Row_json.to_string ~schema writes validated rows with a fixed member order and final newline,
so a Git diff shows the field that changed. Unknown fields are refused.
Schema_toml.of_string reads the store's schema.toml; the writer is
Schema_toml.to_string. Its arrays list the admitted statuses and check kinds,
and kinds the admitted row kinds; without it a store admits Beads' built-in
types, bug, feature, task, epic and chore. Each [[label_families]]
entry gives a name and values; ["*"] admits any value in that family. Each
[[fields]] entry declares a structured field of one kind: its kind, name
and type, one of text, integer (with optional min and max), texts
or records, whose own fields are declared inline, one level deep; any field
may be optional. A row's fields live in its row.json under "fields", and
are checked against its kind's declarations: a missing, unknown, mistyped or
out-of-bounds field is refused, named by its path.
An optional [rules] table states what a write must not leave a row
breaking: title_limit and heading_markers for the title, leads_at_most
for the priorities that need a reason and a label from queues,
[[rules.requires]] for a label that needs a label of another family, and
decided and waits for a decision still to be taken. Schema.admit judges
a row against the row it replaces, so a write is refused only for a rule it
introduces; every store write passes it before its ref moves. Schema.owed
lists what a stored row already breaks, and Store_tree.audit names every row
of a commit that its schema does not admit, as tk check prints them.
Schema_candidate.v validates a schema and all its rows together.
Schema_candidate.rewrite applies replacements to both in memory and returns a
candidate only if every result is valid and each row keeps its id. The store
writes that candidate as one Git tree.
Store_tree.load ~repo ~commit reads schema.toml and the row files from that
commit's tree with nox-git-eio. It checks the SHA-256 shard of each row id
and returns the source tree id with the validated candidate, so an index can be
tied to the exact tree it describes.
Distributed coordination defines the shared machine-local authority, cross-machine convergence and ref decision model.
The package's current test gate is:
dune build @ocaml-tracker/runtest