Commitment tracking for LLM agents — a deontic scoreboard of the agent's own commitments, entitlements, and incompatibilities.
Project description
scorekeeper
Commitment tracking for LLM agents — a deontic scoreboard of the agent's own commitments, entitlements, and incompatibilities, maintained outside the agent's authority.
Long-running agents decide on Postgres at step 3 and write MongoDB code at step 47. scorekeeper treats this as a normative problem, not a memory problem: every non-trivial decision becomes a first-class commitment record with entitlement (provenance — did the user say it? did a tool show it? or did the agent just generate it?), and revisions are gated: an externally grounded revision is a legitimate SUPERSEDE; an ungrounded one is a BRANCH-CONFLICT (drift) surfaced back to the agent. A commitment with no provenance at all is what a hallucination looks like in this vocabulary — it gets a CHALLENGE.
Phase-0 evidence (paired runs, planted scenarios): the bare agent drifted against its own database decision; the scorekept twin held. False-conflict rate 0, token overhead +0.6 %. Full report in the repository.
Install
pip install scorekeeper # core library + CLI
pip install "scorekeeper[mcp]" # + MCP server (scorekeeper-mcp)
Claude Code (primary integration)
git clone https://github.com/michalstrnadel/scorekeeper
claude --plugin-dir ./scorekeeper/claude-code-plugin
Four hooks do the work: SessionStart injects the normative digest (and re-injects it after context compaction — the exact place summarizers drop it), PostToolUse(Edit|Write) runs a millisecond content scan against pinned choices, Stop extracts the turn's commitments (async by default — a detached worker, zero added latency; findings surface on the next prompt), PreCompact backs up the board.
MCP (any harness)
SCOREKEEPER_ROOT=/path/to/project scorekeeper-mcp
Tools: get_scoreboard, get_digest, assert_commitment, check_compatibility (dry-run), supersede, challenge, retract. Writes route through the same validated operator pipeline as the hooks — the agent cannot bypass the scorer.
Library
from scorekeeper import Store
from scorekeeper.extract import ExtractedCommitment
from scorekeeper.operators import apply
store = Store("/path/to/project")
result = apply(store, [ExtractedCommitment(
claim="The primary database is PostgreSQL 16.",
kind="decision",
scope=["topic:persistence", "attr:persistence.primary_db=postgresql"],
entitlement={"source": "user_utterance"},
)])
print(store.render_digest())
Storage is transparent and git-committable: .scorekeeper/commitments/*.yaml, an append-only log.jsonl audit trail, and a generated scoreboard.md. Nothing is ever deleted — statuses transition.
Model backends
Extraction and Tier-1 detection need a small LLM; local open-source models are first-class. Auto-detection order: SCOREKEEPER_MODEL_URL (any OpenAI-compatible endpoint — Ollama, LM Studio, vLLM) → ANTHROPIC_API_KEY (Haiku) → headless claude -p.
License
Apache-2.0. Theory, benchmark, and specs: github.com/michalstrnadel/scorekeeper.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scorekeeper-0.1.1.tar.gz.
File metadata
- Download URL: scorekeeper-0.1.1.tar.gz
- Upload date:
- Size: 93.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
72f6d52f577a4ba49dc6a9cae3847d79e6a228eca24b9e4122cbd83b41086a27
|
|
| MD5 |
41d4fc5d927b9a5a0dd938aee9b4c611
|
|
| BLAKE2b-256 |
3f8d0e3953bf24b3fee3f45acc155327500ea1456193b29295cea57c954094d8
|
Provenance
The following attestation bundles were made for scorekeeper-0.1.1.tar.gz:
Publisher:
release.yml on michalstrnadel/scorekeeper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scorekeeper-0.1.1.tar.gz -
Subject digest:
72f6d52f577a4ba49dc6a9cae3847d79e6a228eca24b9e4122cbd83b41086a27 - Sigstore transparency entry: 2136555656
- Sigstore integration time:
-
Permalink:
michalstrnadel/scorekeeper@246ad9f704c2e28fcebc031989b22674323eda5f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/michalstrnadel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@246ad9f704c2e28fcebc031989b22674323eda5f -
Trigger Event:
push
-
Statement type:
File details
Details for the file scorekeeper-0.1.1-py3-none-any.whl.
File metadata
- Download URL: scorekeeper-0.1.1-py3-none-any.whl
- Upload date:
- Size: 30.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58f183752420b69753bc04882e817631cea56d1ec1bf849d97e8dc6ffd7a6f5e
|
|
| MD5 |
3b49bd89d8d359f370629b1cea208172
|
|
| BLAKE2b-256 |
30d1123c3c13270b903d3170b7e7015d04b3e0dd9404189dde337fdb5046a861
|
Provenance
The following attestation bundles were made for scorekeeper-0.1.1-py3-none-any.whl:
Publisher:
release.yml on michalstrnadel/scorekeeper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scorekeeper-0.1.1-py3-none-any.whl -
Subject digest:
58f183752420b69753bc04882e817631cea56d1ec1bf849d97e8dc6ffd7a6f5e - Sigstore transparency entry: 2136555729
- Sigstore integration time:
-
Permalink:
michalstrnadel/scorekeeper@246ad9f704c2e28fcebc031989b22674323eda5f -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/michalstrnadel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@246ad9f704c2e28fcebc031989b22674323eda5f -
Trigger Event:
push
-
Statement type: