Skip to main content
Glama
vietqtran

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: MCP Memory Server

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

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides persistent memory for AI coding assistants, storing and retrieving architectural decisions, patterns, and solutions across sessions using semantic search, while also offering git integration for commit messages and code expertise mapping.
    MIT
  • 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.
    18
    9
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables storing, querying, and managing decision traces with semantic search using Voyage AI embeddings and ChromaDB. Supports outcome tracking and category filtering for software development decisions.
  • A
    license
    Not graded
    quality
    B
    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

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vietqtran/decision-graph'

If you have feedback or need assistance with the MCP directory API, please join our Discord server