Skip to main content

agent-decision-log

Your agent's decisions survive the session.

A tiny, dependency-free system for anyone who works with AI coding assistants or builds their own agent loops. decisions.txt records what your agent CHOSE and WHY - so the next session starts from "we already decided X" instead of re-exploring it. The companion to agent-error-log (which records what broke); together they give an agent a memory for both its mistakes and its choices.

CI checks on master release license python dependencies-0 Visitors companion

Why

An agent repeats bad decisions far more often than it repeats crashes. A bug has a stack trace - it forces itself to be noticed. A bad decision is invisible: "I used regex instead of an AST parser" works, nothing flags it, and the next session re-makes the same choice in the dark.

The pain is at session start: a new chat has no context, so it re-asks questions the last session already answered and re-explores tradeoffs the last session already settled. This log fixes recall at boot time.

Quick start

# 1. One-command adoption (scaffolds decisions.txt / rules.txt / notes.txt)
python check_decisions.py --init

# 2. Start each session with boot-time recall
python start.py            # or double-click start.bat (Windows)

# 3. Log decisions at forks in the road
python check_decisions.py --decide

# 4. Validate the log
python check_decisions.py

What a decision looks like

[2026-08-09 14:32] DECISION: used regex instead of AST parser
  REASON: faster for the simple case, file was small
  FILES: src/parser.py
  STATUS: LOCKED

Three states, one mental model:

STATUS Meaning SUPERSEDES?
LOCKED the decision stands optional (resolving OPEN)
OPEN deferred; needs a call next session no
REVISED changed your mind (append-only) required - points back

History is never rewritten. A correction is a new entry pointing back:

[2026-08-10 09:15] DECISION: moved parser to AST
  REASON: file grew past 200 lines; regex became unmaintainable
  FILES: src/parser.py
  SUPERSEDES: 2026-08-09 14:32
  STATUS: REVISED

The fork rule (when to log)

Log a decision when reversing it would cost time, or when you actively considered an alternative and picked one.

That's the whole rule. start.py enforces it by embarrassment: it shows the last session's decisions at boot, so picking a different path now without a REVISED entry is visibly inconsistent - not blocked, just accountable.

Tooling reference

Command What it does
python check_decisions.py validate the log (exit 0 = healthy)
--decide scaffold a new decision (interactive; LOCKED + SUPERSEDES is the manual form of --resolve)
--revise <ts> change a decision: append REVISED superseding ts
--resolve <ts> settle an OPEN decision: append LOCKED superseding ts
--has-open gate: exit 1 if any OPEN decision is still current
--recent [N] show the last N decisions with currency
--stats show analytics: status mix, reversal rate, volatility
--review distill repeated reversals into proposed rule drafts
--review --apply write the proposals into rules.txt §7 (LESSONS)
--init [--target DIR] one-command adoption + health check + self-test
--check-commit FILE gate: exit 0 only if the commit message in FILE names a logged decision

How the currency rule works

An entry is current unless a newer entry's SUPERSEDES points at it. Append-only means that check is deterministic and free: a LOCKED decision whose timestamp appears in a later entry's SUPERSEDES is shown as SUPERSEDED BY <ts> at boot. Resolving an OPEN decision uses the same move - append a LOCKED entry with SUPERSEDES - so three states need exactly one append rule.

The compounding loop

--review looks for decisions that were LOCKED and then changed (reversals). Two or more reversals on the same topic produce a proposed rule:

Proposal: default to the most recent decision on <topic> unless the
context genuinely changed; when it does, log a REVISED entry that says why.

--review --apply writes proposals into rules.txt §7 (LESSONS) as drafts. A human confirms them. Failures teach rules (agent-error-log --lessons); decisions teach rules (this --review) - both feed the same permanent memory.

Each proposal also quotes the REASON behind every reversal, so the draft shows why the decision kept changing - not just that it did.

Grouping is by heuristic, not taxonomy: the first FILES basename when a decision names files, else the first three words of its title. Two entries on the same basename in different folders merge into one topic - fine for spotting volatility, not a perfect classification.

FAQ

Why not just use a NOTES.md? A notes file is where decisions go to be forgotten - nothing parses it, nothing gates on it, nothing surfaces it at boot. This log is a structured, validated, append-only record that start.py reads and check_decisions.py keeps honest.

Isn't this just ADRs (Architecture Decision Records)? It's the same instinct applied to agent sessions: ADRs have no boot-time recall, no currency rule, and no compounding loop that turns repeated reversals into rules. The format is the easy part; recall is the product.

Why soft enforcement? A bug without a log entry is clearly wrong; a decision without a log entry is usually correct - most choices are trivial. So there is no local git hook (unlike the sibling repo); the mechanical backstop is the CI commit-message gate on master merges, and the accountability loop is boot-time recall: the agent's own history is shown back at session start.

Does it work with any agent? Yes - any agent that can read text and run shell commands. Point it at the repo in AGENTS.md, or paste rules.txt into a system prompt. I copied the tool to a scratch folder — will it touch my real repo? No. Default paths resolve relative to the script location (HERE), so a scratch copy logs next to itself. Point at your real log from anywhere with --log path/to/decisions.txt. Can I log unicode (café, em-dash) on Windows? Yes — stdin is reconfigured to UTF-8 like stdout, so piped unicode decision text is stored as-is, never double-encoded.

Development

python _test_decisions.py          # run the unit tests (138, 100% pass expected)
python check_decisions.py          # validate the log
python -m py_compile check_decisions.py start.py

CI runs tests + linter on Ubuntu and Windows across Python 3.9 / 3.11 / 3.12. Releases are cut from CHANGELOG.md by a workflow that creates the tag and a draft GitHub Release - see CHANGELOG.md and the workflow in .github/workflows/release.yml.

Shipping a change (PR workflow)

With branch protection live, direct pushes to master are rejected - GH006: Protected branch update failed ... N of N required status checks are expected - because a fresh commit has no CI checks yet. Every change lands via pull request:

  1. Branch off master and commit with the (AREA: <logged decision>) marker in the message (matching a decision in decisions.txt): git commit -m "feat: ... (AREA: add a --stats analytics command)".
  2. Push the branch, open a PR against master. The six tests + linter matrix jobs run on the PR head.
  3. Squash-merge once checks are green, keeping the (AREA: ...) marker in the squash title. The merge push re-runs CI and the commit-message gate on master - a missing marker leaves the gate red.

This repo ships no local commit-msg hook (deliberate: most decisions are trivial, so boot-time recall is the discipline). The CI gate is the mechanical backstop for the marker - which is why it must survive into the squash title. The gate job skips PR events on purpose: PRs are gated when the merge lands, so the squash title is exactly what gets re-checked on master.

Companion tool

  • agent-error-log - logs what broke, mechanically enforced by a git hook. Reactive memory.

Two tools, same shape, same lifecycle verbs: one prevents repeating failures, this one prevents repeating exploration.

License

MIT - see LICENSE.

Installing with pip (optional)

The single-file adoption story is unchanged - copy check_decisions.py into your project and you are done. The tool is also pip-installable with zero runtime dependencies:

pip install agent-decision-log
decision-log --help
  • The package version is derived from the git tag (setuptools-scm), which the release workflow creates from CHANGELOG.md - there is no version to drift.
  • Run from the installed package, default paths (decisions.txt, rules.txt) resolve against your current directory; an in-place copy keeps resolving against the file's folder.
  • --init works identically from an installed copy (built-in templates).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_decision_log-0.5.0.tar.gz (49.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_decision_log-0.5.0-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file agent_decision_log-0.5.0.tar.gz.

File metadata

  • Download URL: agent_decision_log-0.5.0.tar.gz
  • Upload date:
  • Size: 49.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for agent_decision_log-0.5.0.tar.gz
Algorithm Hash digest
SHA256 e6d6cb054abe116730b2609e98228e55d9862f33ff1cd30335325a3d4db7310c
MD5 e3d024b72be30400c4b1d83721e30068
BLAKE2b-256 a40b0992fb40a3732a94ae22829ca50b9a539faed2e4b47e10eff06ba7926722

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_decision_log-0.5.0.tar.gz:

Publisher: publish.yml on vartiainen1/agent-decision-log

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file agent_decision_log-0.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for agent_decision_log-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cd146906782ee39c0bd820776b824403891eddae182bbac23d288b1e915f44c0
MD5 60cdb721e608c145cac7ca147819b24a
BLAKE2b-256 36fb2983784be540f83f9518ec72ec7a7491a23c1ca4022e39ad37113f0213b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for agent_decision_log-0.5.0-py3-none-any.whl:

Publisher: publish.yml on vartiainen1/agent-decision-log

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page