Skip to main content
LedgerDocs
Docs

How Ledger works

Ledger is the piece of relay that reads your project data and flags patterns you’d otherwise have to notice yourself. It’s a rules engine — think spell-check, not AI. This page explains what it does, what it reads, and how to adjust or turn it off.

Last updated: 2026-04-24 · feature status: beta

What Ledger actually does

A Ledger summary is not a paraphrase of the issue description or the comments — you can already read those on the issue page.

What the summary adds is synthesis: facts you would otherwise have to piece together yourself from the activity log, linked PRs, Figma frames, Sentry errors, and the timeline.

  • How long the issue has been in its current status, compared to your team’s average for that type.
  • Which linked PRs are open, whose review they’re waiting on, what CI says.
  • Whether Figma frames moved after the last dev activity.
  • Whether a linked Sentry error is still firing.
  • Whether any decision-language surfaced in recent comments.

Everything in the panel is a real fact about your issue at the moment the panel was generated. Nothing is invented, rephrased, or inferred from sentiment.

Is Ledger AI?

No. Ledger is a rules engine — the same category of software as a linter, a spell-checker, or a fraud-check rule in your bank’s backend. It runs a fixed set of rules against your project data and returns a structured result.

That distinction matters because when most people hear “AI” in 2026, they think of a large language model — a system trained on a lot of data, producing text that’s sometimes right and sometimes made up. Ledger is none of that. It’s deterministic: the same inputs produce the same output, every time. If a flag fires, you can trace exactly which rule matched and which rows in your database triggered it.

If relay ever ships a feature that does use a language model — for example, drafting commit summaries — that would be a different product, with a different name, and a different set of commitments. Ledger will never be that product.

The six rules

A summary may include one or more flag pills near the top. Each flag is a deterministic rule. There are only six, and they don’t change without a product release.

stuck
The issue has been in its current status for at least stuck_issue_days days (default: 7). Explanation on the panel: “In in progress for N days.”
forgotten_close
A linked PR was merged but the issue is still open. Explanation: “Linked PR merged. Issue is still open.”
regression_risk
The issue was previously closed and reopened within the last 30 days. Explanation: “Reopened within 30 days of being closed.”
live_bug
The issue is typed bug, and a linked Sentry error is still marked unresolved. Explanation: “Linked Sentry error is unresolved.”
design_drift
A linked Figma frame was modified after the most recent dev activity on the issue. Explanation: “Design updated after last dev activity.”
unassigned_hot
The issue is priority critical or high, has no assignees, and is older than new_member_unassigned_hours (default: 24). Explanation: “High priority, no assignee, older than 24h.”

That’s the whole list. If you see a flag on a Ledger summary, one of these six rules matched. The rule’s inputs are recorded so you can check exactly why it fired.

The five templates

The summary panel has one layout, but the emphasis differs based on the issue’s state. Ledger picks one of five templates each time a summary is generated.

  • closed — the issue is closed. A short retrospective: what shipped, when, which PR and deployment carried it.
  • unassigned_hot — the unassigned_hot flag is firing. Priority, age, and any linked Sentry evidence on top.
  • stuck — the stuck or forgotten_close flag is firing. Foregrounds the blocker and pulls recent open questions from the discussion.
  • in_review — a linked PR is open and waiting on review. PR state, latest comment from the assignee, and who the review is waiting on.
  • normal — none of the above. A neutral state snapshot.

The template choice is visible in the panel footer (“template: stuck”) so you can always see which shape was used.

What Ledger reads

Ledger reads only from your own Supabase database. The specific tables:

  • relay.issues — title, type, priority, statuses, timestamps.
  • relay.activity_log — the most recent 20 events for the issue.
  • relay.messages — the most recent 20, excluding deleted.
  • relay.github_prs — state, review state, merged status.
  • relay.figma_embeds — frame name, last modified.
  • relay.sentry_errors — status, event count.
  • relay.vercel_deployments — state, target, commit SHA.
  • relay.org_ledger_settings — the thresholds above.
  • A rolling 90-day average of closed issues in your project, grouped by type, used only for the “team average” callout.

Every one of those tables is in your own Supabase instance, inside your own org boundary. None of it is sent anywhere else.

Ledger’s commitments

Four claims that hold under scrutiny, enforced in code, not policy:

  • Ledger never uses a language model. No LLM, no embeddings, no prompt, no provider call. The engine is deterministic rules in code.
  • Your data never leaves your database for a third-party AI service. Zero egress to any model provider. The summary codepath has no AI-provider SDK imports.
  • Your data is never used to train anything. No model is being trained, globally or per-org. The closest thing to “learning” Ledger does is threshold auto-tuning, described below.
  • Derived data has a retention window. The inputs Ledger used to build older summaries are deleted after 30 days. The summary’s conclusions — flags, template choice, generated body — are kept for historical context.

Relay does, of course, store your project data in your Supabase instance. That’s how the product works. The commitments above are about what Ledger doesn’t do with that data.

How feedback shapes your team’s thresholds

Below each summary there’s a pair of buttons: Useful and Noise. These are optional, per-user, and scoped to your org.

When your team votes a flag as useful, Ledger leaves that flag’s threshold alone. When your team votes it as noise repeatedly, a nightly job loosens the threshold for your org — for example, bumping stuck_issue_days from 7 to 10 if the 7-day setting keeps firing on issues your team doesn’t consider stuck.

The tuner has four constraints:

  • It only reads your org’s feedback. Your votes never affect another team’s thresholds, and vice versa.
  • It can only move thresholds inside a bounded range (e.g., stuck_issue_days cannot drift below 1 or above 90). Those bounds are enforced at the database level.
  • It always logs the change to the audit log, with old value, new value, and the dismiss rate that triggered it.
  • You can turn it off. An admin can set auto_tune_enabled = false and the engine will stay at whatever thresholds you set manually.

How to adjust or turn it off

Adjust a single threshold
Settings → Ledger shows every threshold (stuck_issue_days, sprint_idle_hours, etc.). Any value auto-tuned from its default shows an “adjusted from default” badge with a one-click reset. Admins and owners can change any value within its bounded range.
Turn off auto-tuning
Same panel, toggle auto_tune_enabled off. Thresholds stop moving on their own.
Turn off Ledger entirely
Settings → Ledger, toggle summary_enabled off. The summary panel disappears from every issue in your org. No regenerations happen. Existing summaries are retained but not displayed.

All three are admin-only. Members can see the current values but cannot change them.

Why rules, not a language model

We get asked this a lot, so here’s the honest answer.

  • Rules are deterministic. Given the same inputs, Ledger produces the same summary every time. That makes it auditable — when you see a flag, you can trace exactly which rule fired and which rows triggered it.
  • Rules are cheap. A summary takes milliseconds to generate and costs nothing per request. No token budget, no provider outage to worry about.
  • Rules keep your data inside your database. A language-model feature, done properly, requires sending at least excerpts of your customer content to a model provider. We’ve chosen not to do that here.
  • Rules are correctable. When a rule misfires, we change six lines of code and ship a release. You can see the change in the changelog. A fine-tune has no comparable pathway.
If you’ve been burned by AI features that promised magic and delivered surprises, Ledger is the opposite of that by design. Boring, deterministic, visible, private.
← Back to Ledger