Skip to main content
Glama
decision-graph

decision-graph

by vietqtran

decision-graph

English · Tiếng Việt

CI License: MIT Python 3.10+

Decision memory for codebases worked on by AI agents.

A code graph tells you what the code does. decision-graph tells you why it is that way — when a business rule appeared, who decided it, what alternatives were rejected, and whether the decision still holds.

git blame gives you a commit message. It does not tell you that a customer's CTO asked for a second approval tier in a meeting, that a separate module was considered and rejected as unmergeable, or that the threshold was lowered six months later by someone else.

Language- and framework-agnostic. Works in any repo.

Why

The pain is sharpest when one base product is extended per customer — but it shows up anywhere business logic accumulates:

  • An agent "improves" a rule that was deliberately written that way for one tenant.

  • Nobody remembers whether an odd-looking branch is a bug or a requirement.

  • The same rejected approach gets proposed again every few months.

  • Decisions live in Slack threads, ticket comments, and people's heads.

AI agents make this worse, because they have no implicit memory of the last six months of meetings — but they will follow a written record if one exists.

Related MCP server: arcane

Design principles

  • Markdown is the source of truth. One .md file per decision, in git, reviewable in a PR.

  • SQLite is only an index. Delete decisions/_index/ and rebuild any time.

  • Agents may not invent decided_by. An agent can only create a draft; promoting it to active requires a human.

  • Recording is a side effect of coding, not a chore to remember — hooks prompt at the right moment.

  • Detection reads git, not tool events. Edits made with sed, heredocs, git apply, or a plain editor are caught just like Edit/Write tool calls.

Install

Not on PyPI yet — install straight from GitHub:

uv tool install "decision-graph[mcp] @ git+https://github.com/vietqtran/decision-graph"
# pipx
pipx install "decision-graph[mcp] @ git+https://github.com/vietqtran/decision-graph"

# one-off, no install
uvx --from "git+https://github.com/vietqtran/decision-graph" decision-graph --help

# local development
git clone https://github.com/vietqtran/decision-graph && cd decision-graph
uv venv && uv pip install -e ".[mcp]"

Requires Python 3.10+ and a SQLite build with FTS5 (standard on macOS, Debian/Ubuntu, and the official Python images).

Quick start

cd /path/to/your/repo
decision-graph init

decision-graph add --scope acme --module deals/approval \
  --title "Second approval tier for deals over 500M" \
  --file src/approval.py --tag override-base --stdin < body.md

# a human confirms who decided — the agent cannot do this step
decision-graph confirm acme-2026-08-26-second-approval-tier --by "Jane Doe (CTO, Acme)"

decision-graph search "two-tier approval" --scope acme
decision-graph history src/approval.py   # every decision that touched this file
decision-graph overlay acme              # how acme differs from base, and why

Core concept: scope

scope is the axis that separates contexts — a customer, a product line, a team, or _base for decisions that apply everywhere.

Filtering by scope happens before full-text ranking, which is what stops one tenant's rules from bleeding into answers about another. In a repo serving many customers, this is the single most important field.

Layout

decisions/
  _template.md
  _base/                          # applies to every scope
  acme/2026-08-26-approval.md
  viettel/2026-05-20-inventory.md
  _index/decisions.db             # generated — gitignored
.decision-graph.yml               # per-repo watch/ignore patterns

A record's frontmatter:

id: acme-2026-08-26-second-approval-tier
scope: acme
module: deals/approval
title: "Second approval tier for deals over 500M"
status: active                 # draft | active | superseded | deprecated
lifecycle_stage: maintenance   # design | dev | uat | golive | maintenance
supersedes: acme-2026-03-12-single-tier
decided_by: "Jane Doe (CTO, Acme)"
requested_by: "John Smith (PM)"
decided_at: 2026-08-26
linked_files: [src/approval.py]
linked_commit: 8f3a2c1
session_id: abc-123            # agent session that produced the change
ticket: JIRA-482
tags: [approval, override-base]

The body follows decisions/_template.md: Context / Alternatives considered / Decision / Impact / Open risks.

Alternatives considered matters more to agents than to humans — it is what stops an agent from re-proposing the approach that was already rejected.

supersedes chains records instead of deleting them, so the audit trail survives.

Metadata filters first (scope, module, status, lifecycle_stage, file, tag), then SQLite FTS5 ranking. Diacritics are folded, so duyet don hang matches Duyệt đơn hàng.

decision-graph search "approval"                    # active decisions only, by default
decision-graph search --scope acme --status any
decision-graph search --file src/approval.py
decision-graph search "pricing" --tag override-base --json

Agent integration

Which trigger to use

Situation

Trigger

Claude Code runs on the same machine as the repo

Claude Code hooks — can block, strongest

Claude Code runs elsewhere (SSH / VM / remote)

Git hook — reminds, cannot block

Humans committing without an agent

Git hook + check in CI

Installing both is fine; each goes quiet once a decision is recorded.

Claude Code hooks

decision-graph hooks install --target /path/to/repo
  • PostToolUse(Edit|Write|MultiEdit) records which files a session touched.

  • Stop inspects git plus that record. If business-relevant files changed and no decision was written, it returns decision: "block" with instructions — the agent must act instead of finishing.

The agent gets exactly two ways out:

decision-graph skip --session <id> --reason "renamed variables only"
decision-graph add ... --session <id>   # then ask the human, then confirm

stop_hook_active is honoured, so this never loops.

Install hooks where Claude Code actually runs, not where the code lives. If you run Claude Code on a VM and only proxy shell commands to the machine holding the repo, that machine's .claude/settings.json is never read — use the git hook instead.

Git hook

decision-graph hooks install --git --target /path/to/repo

Installs .git/hooks/post-commit calling decision-graph remind. It never blocks a commit. Because agents run git through their shell and read stdout, the reminder lands in the agent's context anyway.

It stays silent once a decision links to that commit.

MCP server

One entry, declared once at user level — the server follows whichever repo the session has open, so there is no path to keep in sync:

{
  "mcpServers": {
    "decision-graph": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/vietqtran/decision-graph",
               "decision-graph-mcp"]
    }
  }
}

It asks the client which directory the session is working in (MCP roots), falling back to the working directory. Repos without a decisions/ directory are skipped rather than guessed at. Add --path /path/to/repo only to pin the server to one repo.

Tools: search_decisions, get_decision, get_decision_history, get_decision_chain, get_overlay_map, list_scopes, add_decision.

See docs/MCP.md.

Filtering noise

Not every commit is a business decision. Typos and pure refactors should not generate records.

Defaults ignore tests, lockfiles, node_modules, build output, coverage reports, assets, and i18n files. Narrow further per repo:

# .decision-graph.yml
watch:
  - "src/domain/**"
  - "app/services/**"

An empty watch means everything not in ignore counts.

CI

decision-graph check --git

Emits {"needs_decision": bool, "watched_files": [...], ...} — wire it into a PR warning.

Documentation

Development

uv venv && uv pip install -e ".[mcp]"
.venv/bin/python -m unittest discover -s tests

No runtime dependency beyond PyYAML; mcp is an optional extra.

Prior art

decision-graph is an ADR variant. ADRs record architectural decisions for humans; this records business decisions, per tenant, in a form agents can query — with automatic capture and a human confirmation gate.

License

MIT

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides long-term memory for AI coding agents, enabling them to remember, search, and organize information across sessions and platforms like Claude Code, ChatGPT, and Cursor.
    20 npm
    8
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides persistent, searchable memory and knowledge capture for AI-assisted development, enabling agents to retain decisions, bugs, and patterns across sessions and projects.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Self-hosted decision memory for AI coding agents. Captures decisions with the alternatives you rejected, and warns before an agent re-proposes a rejected approach.
    4
    89
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Gives multiple AI coding agents a shared, persistent memory by indexing your code and documentation into a vector database with AST-aware chunking and hybrid semantic/keyword search. Agents can search across projects and store, update, or forget decisions, conventions and lessons learned, all self-hosted with local embeddings.
    MIT