work-ledger

module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2026 License: Apache-2.0

README

Motus Work Ledger

Motus keeps the fix with the failure. It records selected facts about a command run, lets you add the reason the failure mattered, and connects that finding to the successful run that resolved it.

Git records source changes, not whether a selected command ran or how it ended. Terminal scrollback disappears and CI logs live elsewhere. Motus gives selected runs stable IDs, searchable findings, and deterministic JSON receipts for closed runs, all in a local SQLite ledger.

Install

With Go 1.26.5 or newer:

$ go install github.com/motus-os/work-ledger/cmd/motus@latest

Go places the binary in GOBIN, or in GOPATH/bin when GOBIN is unset. Make sure that directory is on your PATH.

Prebuilt archives are available from the latest release. Each release includes SHA-256 checksums, SBOMs, and GitHub artifact attestations. Verify the archive, unpack it, and place motus or motus.exe on your PATH.

Verify a release archive

Replace ARCHIVE_NAME with the exact downloaded filename. Attestation verification uses the GitHub CLI.

On macOS:

$ grep "  ARCHIVE_NAME$" checksums.txt | shasum -a 256 -c -
$ gh attestation verify ARCHIVE_NAME --repo motus-os/work-ledger

On Linux:

$ grep "  ARCHIVE_NAME$" checksums.txt | sha256sum -c -
$ gh attestation verify ARCHIVE_NAME --repo motus-os/work-ledger

On Windows PowerShell:

$archive = "ARCHIVE_NAME"
$expected = (Get-Content checksums.txt | Where-Object { $_ -like "*  $archive" }).Split()[0]
$actual = (Get-FileHash $archive -Algorithm SHA256).Hash.ToLowerInvariant()
if ($actual -ne $expected) { throw "checksum mismatch" }
gh attestation verify $archive --repo motus-os/work-ledger

The macOS binaries are not Apple-notarized. After the checksum and GitHub attestation pass, remove a browser-added quarantine flag if Gatekeeper blocks the extracted binary:

$ xattr -d com.apple.quarantine /path/to/motus

Confirm the installed command:

$ motus version

Keep a failure and its fix

Run a test, build, script, or tool through Motus. The wrapped command still writes to the terminal. Motus normally returns its exit status; an output-copy failure returns Motus's internal failure status instead. The transcript below is condensed, uses shortened output IDs, and uses YOUR_COMMAND as a placeholder for the command you want to run. Uppercase values are placeholders.

$ motus wrap -- YOUR_COMMAND
motus: recorded run_0d27... (failure)
Keep why this failed:
  motus --state-dir /work/project/.motus finding add --run run_0d27... --file -

Inspect the run:
  motus --state-dir /work/project/.motus run receipt run_0d27...

Use the printed command to keep the explanation. Finding text is read from a file or standard input, not from a command-line argument. Type one line, then press Ctrl-D on macOS or Linux. On Windows, press Ctrl-Z and then Enter.

$ motus finding add --run FAILED_RUN_ID --file -
The generated file was stale.
Recorded finding_c896... (open)
Run: run_0d27...
Summary: The generated file was stale.

Make the change, then run the same check through Motus. After it succeeds, connect the finding to that run. Enter the closure note through standard input and finish it with the same EOF key sequence.

$ motus wrap -- YOUR_COMMAND
motus: recorded run_c0e5... (success)

$ motus finding close FINDING_ID --disposition resolved --run SUCCESS_RUN_ID --file -
Refreshed the generated file before running the check.
Closed finding_c896... (resolved)
Resolving run: run_c0e5...

Motus keeps the original finding and appends a separate closure instead of rewriting it. When the problem returns, search your own words and inspect both runs:

$ motus finding list --query stale
FINDING ID       STATE     RECORDED (UTC)         ORIGIN RUN   SUMMARY
finding_c896...  resolved  2026-07-24T14:32:11Z  run_0d27...  The generated file was stale.

$ motus finding show finding_c896...

What is recorded

  • a random run ID and timestamps
  • the executable's base name and argument count
  • the Git repository name, commit, and pre-run dirty state when available
  • stdout and stderr byte and newline counts
  • exit code or terminating signal when available, and outcome
  • structured run events created by Motus
  • finding summaries, hypotheses, next steps, and closure notes that you explicitly supply

Motus does not store command argument values, wrapped-command stdin, raw stdout or stderr, environment variables, source files, prompts, or agent transcripts. Finding text is the exception: Motus stores the validated finding content you submit through a file or stdin. It does not send ledger data over the network.

State and commands

By default, Motus uses .motus/ledger.db at the current Git root. Outside a Git repository, it uses the current directory. Override this with --state-dir PATH or MOTUS_STATE_DIR.

Motus creates state directories with private POSIX permissions. If you create a custom state directory yourself, restrict it to the current user before use.

motus wrap -- COMMAND [ARG ...]  Run a command and record selected metadata
motus run list [OPTIONS]         List and filter recorded runs
motus run receipt RUN_ID         Write a JSON receipt for a closed run
motus finding add [OPTIONS]      Connect an authored finding to a run
motus finding list [OPTIONS]     List and search findings
motus finding show FINDING_ID    Show a finding and its run context
motus finding close [OPTIONS]    Resolve or dismiss a finding
motus doctor [--json]            Check local database consistency
motus version                    Print version information

Add .motus/ to the project's ignore file if the ledger should remain outside version control.

Wrapped command behavior

motus wrap starts the command directly, without a shell. It forwards stdin and copies stdout and stderr to their original destinations. Motus records byte and newline counts observed before the command finishes or Motus terminates it. Because output is copied through pipes, a program that checks for a terminal can format its output differently than it would when run directly. If an output destination closes, Motus stops the command tree and records a failure. The wrapped process keeps the same environment and operating-system capabilities it would have when run directly; Motus is not a sandbox.

Trust boundary

A Motus receipt is a producer-controlled process record. Findings are also producer-controlled records: their text is authored, not independently verified or inferred by Motus. Database triggers block ordinary updates and deletes, and motus doctor checks the current schema, hashes, sequences, foreign keys, terminal records, and finding links. A person who controls the database file can replace those controls and rewrite a self-consistent history. Motus does not sign records, provide an independent observation, or prove that the recorded work was correct.

The receipt states this boundary as "trust_model":"producer-controlled". See SECURITY.md for the full security model and ARCHITECTURE.md for the data flow and storage design.

Development

The normal checks use standard Go commands:

$ go test -race ./...
$ go vet ./...
$ go build ./cmd/motus

The default pull-request workflow runs once on Ubuntu. Release builds run the suite natively on Ubuntu, macOS, and Windows first; the same native check can also be started manually.

See CONTRIBUTING.md before proposing a change.

License

Apache License 2.0. See LICENSE. Binary archives also include the applicable third-party notices.

Directories

Path Synopsis
cmd
motus command
internal
buildinfo
Package buildinfo exposes release metadata injected by the build.
Package buildinfo exposes release metadata injected by the build.
capture
Package capture runs a child process while forwarding and measuring its output without retaining the output or command arguments.
Package capture runs a child process while forwarding and measuring its output without retaining the output or command arguments.
cli
Package cli implements the Motus command-line interface.
Package cli implements the Motus command-line interface.
gitmeta
Package gitmeta reads a small, bounded set of Git repository metadata.
Package gitmeta reads a small, bounded set of Git repository metadata.
ids
Package ids creates opaque identifiers for ledger records.
Package ids creates opaque identifiers for ledger records.
statepath
Package statepath resolves the one state directory used by the CLI.
Package statepath resolves the one state directory used by the CLI.
store
Package store provides the local, producer-controlled SQLite ledger.
Package store provides the local, producer-controlled SQLite ledger.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL