claimdag-cli 0.8.0

claimdag command line over a work.bin directory
<p align="center">
  <img src="docs/logo/icon.svg" width="120" height="120" alt="claimdag">
</p>

# claimdag

**What is claimable right now?** CAS claim and complete on a DAG. One writer. Unpacked Cap'n on disk.

The host process is the sole mutator. Snapshot is `work.bin` (mmap).
This crate has no RPC surface.

Docs: https://leidarljos.github.io/claimdag/

| Page | What it answers |
|---|---|
| [Getting started]https://leidarljos.github.io/claimdag/getting-started.html | Upsert, claim, complete on a scratch graph |
| [How-to]https://leidarljos.github.io/claimdag/howto.html | Leases, release, ready |
| [Reference]https://leidarljos.github.io/claimdag/reference.html | Verbs, generation, snapshot |
| [Explanation]https://leidarljos.github.io/claimdag/explanation.html | Why completing does not close a ticket |

The seat that claims through this graph is documented at https://leidarljos.github.io.

```console
$ cargo add claimdag
$ cargo binstall claimdag-cli claimdag-mcp claimdag-tui
```

`cargo binstall` fetches the prebuilt binaries from the GitHub release.
`cargo install` takes the same names and builds from source.

## First minute

```console
$ export CLAIMDAG_DIR=/tmp/demo-claims
$ a=$(claimdag upsert --summary "parse the manifest header")
$ b=$(claimdag upsert --summary "reject a manifest with no header" --parent $a)
$ claimdag link $a $b
$ claimdag list
092dca29...  ready  task  gen=1  parse the manifest header
71368334...  todo   task  gen=1  reject a manifest with no header
```

```console
$ claimdag --dir /var/lib/seat upsert --summary "land the adapter"
$ claimdag --dir /var/lib/seat list
$ claimdag --dir /var/lib/seat list --json --all
$ claimdag --dir /var/lib/seat claim <id> --assignee <actor>
$ claimdag --dir /var/lib/seat release <id> --actor <actor>   # hand it back unfinished
$ claimdag --dir /var/lib/seat complete <id> --actor <actor>
$ claimdag --dir /var/lib/seat archive <id>
$ claimdag --dir /var/lib/seat link <parent> <child>
```

## Law

- One in-process graph. The host is the sole mutator.
- Snapshot is unpacked Cap'n `work.bin`. Hosts mmap it.
- Ids are 128-bit `WorkId`. Kind, status, and role are closed enums.
- Summary is the only open text field.
- `claim` is CAS on `gen` (omit `--gen` to ignore). Terminal is sticky.
- `archive` is a flag on a terminal node, not a new status and not a delete.
- Default `list` is live work only (`--terminal`, `--archived`, `--all`).
- `link` is a boolean hard dependency.
- `ready` is unblocked and unheld, deepest chain first. Take the first one.

## Which ready node

`ready` orders by the longest chain of unfinished work below a node, unit
cost, then recency, then id: the list-scheduling priority (Hu, DOI
10.1287/opre.9.6.841; Graham, DOI 10.1137/0117039; HEFT, DOI 10.1109/71.993206).
Every row carries `waiting_below`, so the order is visible rather than trusted.

For multi-worker concurrency, `ready --balanced` and `claim-next` apply the Power
of Two Choices (P2C) bounded by critical slack ($\Delta$). Probes are seeded with
the requesting worker ID to prevent herding on the top node while strictly prioritizing
role affinity and preserving critical path progress.

## WorkGraph pane

`claimdag-tui` draws the parent forest and claims, completes and archives
through the same `WorkGraph` calls the command line makes, so an action a
stranger may not take fails in the pane too. Bindings, the actor id and
the handle names are in the [how-to](https://leidarljos.github.io/claimdag/howto.html).

```console
$ CLAIMDAG_DIR=/var/lib/seat claimdag-tui
```

Docs: [docs/orgmode/architecture.org](docs/orgmode/architecture.org).
Schema: [schema/claimdag.capnp](schema/claimdag.capnp).

License: Apache-2.0 OR MIT.