Where dapilot state lives and the rules for touching it, work dirs keyed by content hash, the run ledger, locks. Loaded into every agent. Workers write only their stage's outputs; leads talk to the ledger through ledger.py; nobody edits state.json by hand.
Installs into .claude/skills of the current project.
Are you the author of Work Ledger?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/3dapi-inc-work-ledger)
---
name: work-ledger
description: Where dapilot state lives and the rules for touching it, work dirs keyed by content hash, the run ledger, locks. Loaded into every agent. Workers write only their stage's outputs; leads talk to the ledger through ledger.py; nobody edits state.json by hand.
user-invocable: false
---
# work-ledger
```
work/<sha256>/ one model, forever, whatever it was called on upload
source.<ext> the upload
meta.json original name, size, hash, first seen
<stage outputs> analysis.json, quote.json, renders/, comparables.json, price.json, design/, design.json
log.md one paragraph per stage
.lock present while a worker holds the dir
<stage>.failed.json the ledger's marker: the stage failed (or .blocked.json: asked a
person); no run dispatches it until a person clears the file
runs/<id>/
state.json written only by ledger.py
report.md written only by ledger.py report
```
The ledger script is `${CLAUDE_PLUGIN_ROOT}/scripts/ledger.py`. Run it with
`$PY`, from the project root, or with `DAPILOT_PROJECT_DIR` set.
## Workers
1. Your brief names `workdir`, `requires`, `produces`. First check: if every
`produces` path exists, print a `cached:true` result and stop.
2. Write `.lock` in the work dir containing your run, stage and agent name.
If a `.lock` already exists, return `ok:false` with reason
`locked by <contents>` and stop.
3. Read only the files in `requires`. Write only the files in `produces`,
plus `log.md`. Nothing else in the work dir is yours.
4. Remove `.lock` before printing the result line, on success or failure.
5. Never read or write another item's work dir. Never touch `runs/`.
## Leads
```
$PY ledger.py init --run $RUN --folder <dir> --department <dept> # once, by the director
$PY ledger.py next --run $RUN # briefs ready now; each is marked running
$PY ledger.py record --run $RUN --result - [--tokens N --model M] # one per result line
$PY ledger.py status --run $RUN # counts, ready, work_left, over_budget
$PY ledger.py report --run $RUN # writes report.md
```
- Dispatch exactly the briefs `next` returned, nothing else. Pass each brief
to a worker verbatim as its prompt.
- Record every result you receive, including bad ones; the ledger decides
whether it counts. Pass the worker's token usage when you can see it.
- Loop: `next`, dispatch all briefs in one message so they run in parallel,
record each result, `status`. Stop when `work_left` is false.
- Dispatch each brief to its `agent` when it names one, else the department worker.
- Never edit `state.json`. Never delete an output. Never remove a `.lock`
younger than its stage's `minutes_per_stage` (else `max_worker_minutes`);
the ledger handles stale ones.
## Everyone
The content hash is the identity of a model. Two uploads of the same bytes
are one item. A renamed file is the same item. Outputs are never
regenerated by an agent; a person deletes them to force a redo.