feat: an accounting view of accepted tasks by machine and by workload #782

Merged
admin merged 1 commits from feat/21-accounting-view into dev 2026-10-31 02:19:52 +00:00
Owner

Part of #21.

What

An accounting view beyond job record v1: totals by machine and by workload over a span of time, as a pool API call and a CLI command with CSV export. It follows the boundary agreed on #21 and in #476: the accepted task is the unit, together with the coordinator-observed basis it was accepted on. It has no weights, prices or measured durations, and the v1 record is unchanged. This answers excho0's v1-vs-v2 question on #21 in favour of a read-only projection: no v2 section and no parameter hash.

Basis Meaning Credited to
agreement two or more workers returned the same result each agreeing worker
audit the coordinator re-ran the task and matched the worker
unchecked one result taken as it came (no check, spot check passed over, audit inconclusive) the worker
caught the coordinator's audit disagreed and took its own result nobody (counted against the worker as caught)

Per machine: jobs, attempts, failed attempts, accepted tasks by basis, caught, outvoted.
Per workload: jobs (succeeded/failed/cancelled), tasks, attempts, failed attempts, accepted tasks by basis (each counted once), machines, and wall seconds (submit to end on the coordinator's clock, labelled as not compute time).

How

  • packages/accounting (new, no I/O): Events(job) gives a finished job's accepted-task events. Summarize(Input{Jobs, Range, Composite}) gives the totals. A job made of jobs counts as a job, and its steps count for themselves, so the coordinator is never credited as a machine.
  • NodeService.GetAccounting(from, to) (proto/sisyphus/v1/node.proto). It has the client role. A client admitted to the pool gets only the jobs it submitted, as with GetJob/own. The node's own key gets every job. A range whose end is not after its start is INVALID_ARGUMENT.
  • sisyphusd accounting [--last 24h|7d|30d|<duration>] [--from DATE|RFC3339] [--to …] [--by machine|workload] [--csv]. One column table drives both the printed table and the CSV.
  • Extension point for #776 (mining time, estimated power cost per machine): new figures go on accounting.Machine and MachineTotals (the proto comment says so). They come in through accounting.Input beside Jobs, so no caller changes, and each needs one entry in machineColumns to show up in both the table and the CSV. No mining code is included.
  • Only jobs the coordinator still holds are counted (--keep-jobs, 30 days by default). The README says so.

The desktop page is the next PR. It needs a local-API (node/v1) call and a page in apps/sisyphus, and docs/desktop-backend.md now notes it as still to come.

Tests

  • packages/accounting: each basis and who gets credited, ranges (from inclusive, to exclusive, unbounded), per-machine and per-workload totals across succeeded, failed and cancelled jobs, restored attempts with no worker, renamed machines, composite jobs, and a clock that went backwards. Coverage is 100%.
  • apps/sisyphusd: a real pool test covering primes jobs, a graph and two clients (the node sees all, each client sees only its own, empty range refused); a real node with the CLI table, --csv and --csv --by workload, and --to before the job; a fake node that checks the exact from/to sent for --last, --from and --to, and every error path including a failing writer.
  • go test -race -count=5 on packages/accounting, packages/jobrecord, apps/sisyphusd/{access,api,coordinator} and the new main-package tests; the full apps/sisyphusd package once with -race. All pass. gofmt -l apps packages skills is empty, and go vet ./... and staticcheck 2026.2.2 are clean.
  • Coverage: I did not run make cover (it needs Kubo, Cluster and Docker). I checked the changed lines with -coverprofile/-coverpkg instead, and every new statement is covered. packages/accounting is added to COVERED in the Makefile.

Docs

  • apps/sisyphusd/README.md: a new Accounting section (bases, columns, what is and is not counted, client scoping, #776), the usage line and a layout row.
  • docs/research/token-economics.md: how the view puts the accepted-task design into practice.
  • docs/desktop-backend.md and docs/security-model.md: the API and the client-scoping rule.
Part of #21. ## What An accounting view beyond job record v1: totals **by machine** and **by workload** over a span of time, as a pool API call and a CLI command with CSV export. It follows the boundary agreed on #21 and in #476: the accepted task is the unit, together with the coordinator-observed basis it was accepted on. It has no weights, prices or measured durations, and the v1 record is unchanged. This answers excho0's v1-vs-v2 question on #21 in favour of a read-only projection: no v2 section and no parameter hash. | Basis | Meaning | Credited to | | --- | --- | --- | | `agreement` | two or more workers returned the same result | each agreeing worker | | `audit` | the coordinator re-ran the task and matched | the worker | | `unchecked` | one result taken as it came (no check, spot check passed over, audit inconclusive) | the worker | | `caught` | the coordinator's audit disagreed and took its own result | nobody (counted against the worker as `caught`) | **Per machine:** jobs, attempts, failed attempts, accepted tasks by basis, caught, outvoted. **Per workload:** jobs (succeeded/failed/cancelled), tasks, attempts, failed attempts, accepted tasks by basis (each counted once), machines, and wall seconds (submit to end on the coordinator's clock, labelled as not compute time). ## How - `packages/accounting` (new, no I/O): `Events(job)` gives a finished job's accepted-task events. `Summarize(Input{Jobs, Range, Composite})` gives the totals. A job made of jobs counts as a job, and its steps count for themselves, so the coordinator is never credited as a machine. - `NodeService.GetAccounting(from, to)` (`proto/sisyphus/v1/node.proto`). It has the client role. A client admitted to the pool gets only the jobs it submitted, as with `GetJob`/`own`. The node's own key gets every job. A range whose end is not after its start is `INVALID_ARGUMENT`. - `sisyphusd accounting [--last 24h|7d|30d|<duration>] [--from DATE|RFC3339] [--to …] [--by machine|workload] [--csv]`. One column table drives both the printed table and the CSV. - **Extension point for #776 (mining time, estimated power cost per machine):** new figures go on `accounting.Machine` and `MachineTotals` (the proto comment says so). They come in through `accounting.Input` beside `Jobs`, so no caller changes, and each needs one entry in `machineColumns` to show up in both the table and the CSV. No mining code is included. - Only jobs the coordinator still holds are counted (`--keep-jobs`, 30 days by default). The README says so. The desktop page is the next PR. It needs a local-API (`node/v1`) call and a page in `apps/sisyphus`, and `docs/desktop-backend.md` now notes it as still to come. ## Tests - `packages/accounting`: each basis and who gets credited, ranges (from inclusive, to exclusive, unbounded), per-machine and per-workload totals across succeeded, failed and cancelled jobs, restored attempts with no worker, renamed machines, composite jobs, and a clock that went backwards. Coverage is 100%. - `apps/sisyphusd`: a real pool test covering primes jobs, a graph and two clients (the node sees all, each client sees only its own, empty range refused); a real node with the CLI table, `--csv` and `--csv --by workload`, and `--to` before the job; a fake node that checks the exact `from`/`to` sent for `--last`, `--from` and `--to`, and every error path including a failing writer. - `go test -race -count=5` on `packages/accounting`, `packages/jobrecord`, `apps/sisyphusd/{access,api,coordinator}` and the new main-package tests; the full `apps/sisyphusd` package once with `-race`. All pass. `gofmt -l apps packages skills` is empty, and `go vet ./...` and staticcheck 2026.2.2 are clean. - Coverage: I did not run `make cover` (it needs Kubo, Cluster and Docker). I checked the changed lines with `-coverprofile`/`-coverpkg` instead, and every new statement is covered. `packages/accounting` is added to `COVERED` in the Makefile. ## Docs - `apps/sisyphusd/README.md`: a new **Accounting** section (bases, columns, what is and is not counted, client scoping, #776), the usage line and a layout row. - `docs/research/token-economics.md`: how the view puts the accepted-task design into practice. - `docs/desktop-backend.md` and `docs/security-model.md`: the API and the client-scoping rule.
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Sisyphus/Sisyphus#782