Kandryn writes the code. Your team decides what merges.

Kandryn writes only to the repository you connect — nothing merges without your authorization.

src/routes/refunds.tsPROPOSED
export async function createRefund(req, res) {
return await db.transaction(async (tx) => {
Illustrative — the same change the demo below walks through.

One work item, one proposed change

Interactive — sample project

A story from the board, the change Kandryn proposes for it, and the pull request it would open. Sample project — click through it.

Kandryn
Jira connectedGitHub connected
Run #1042SUCCEEDED
PAY-214 · Idempotency keys on the refund endpoint
TRIGGER
Manual
AUTO-COMMIT
Off
REPOSITORY
acme/payments-api
STACK
Node · Express · Drizzle
Synthesia→Raptia recommended·87% confidence“Raptia’s transaction wrapper is the decisive factor.”
RaptiaRecommendedscore 9.2src/routes/refunds.ts
Adds an idempotency guard that reads the header, returns the stored refund on a replay, and writes the row and its ledger entries inside one transaction — matching the repository’s existing Drizzle helper. Synthesia ranked it first.
Correctness94
Readability88
Minimal diff91
Conventions78
AC coverage92
export async function createRefund(req, res) {
  const key = req.header('Idempotency-Key');
  if (!key) return res.status(400).json({ error: 'idempotency_key_required' });

  const existing = await db.query.refunds.findFirst({
    where: and(eq(refunds.userId, req.userId), eq(refunds.idempotencyKey, key)),
  });
  if (existing) return res.status(200).json(existing);

  return await db.transaction(async (tx) => {
    const [row] = await tx.insert(refunds).values({ ...req.body, idempotencyKey: key }).returning();
    await tx.insert(ledger).values(entriesFor(row));
    return res.status(201).json(row);
  });
}
Foveascore 7.1src/lib/idempotency.ts
A smaller in-memory memoiser. Correct for a single process, but it does not survive a restart or share state across the settlement workers, so Synthesia ranked it second.
Correctness72
Readability90
Minimal diff68
Conventions62
AC coverage48
const seen = new Map();

export function refundOnce(key, fn) {
  if (seen.has(key)) return seen.get(key);
  const p = fn();
  seen.set(key, p);
  return p;
}
01The work item
STORYPAY-214
Idempotency keys on the refund endpoint
02The proposed change
src/routes/refunds.ts9.2 / 10
export async function createRefund(req, res) {
  const key = req.header('Idempotency-Key');
  if (!key) return res.status(400).json({ error: 'idempotency_key_required' });

  const existing = await db.query.refunds.findFirst({
    where: and(eq(refunds.userId, req.userId), eq(refunds.idempotencyKey, key)),
  });
  if (existing) return res.status(200).json(existing);

  return await db.transaction(async (tx) => {
    const [row] = await tx.insert(refunds).values({ ...req.body, idempotencyKey: key }).returning();
    await tx.insert(ledger).values(entriesFor(row));
    return res.status(201).json(row);
  });
}
03The pull request
[Kandryn] Idempotency keys on the refund endpoint
Opens once you commit a change above.

Where Kandryn fits

Scoped work from a backlog you already keep — the tickets that are clear enough to do and never quite urgent enough to start.

  • STORYAdd an idempotency guard to an endpoint that never had one.
  • TASKWrite the reporting query behind a column someone asked for.
  • TASKAdd a field to a table, plus the migration that ships it.
  • BUGCover an endpoint with the tests it went to production without.

How it works

The full pipeline, stage by stage →
  1. 01

    Select scoped work

    Point Kandryn at one item on your board. It reads the title, description and acceptance criteria, and pulls in the repository files that relate to them, before anything is written.

  2. 02

    Compare proposals

    Two independent attempts at the same change, scored against each other on correctness, diff size and convention fit — with the reasoning shown.

  3. 03

    Review the change

    The one you choose becomes a branch, a commit and a pull request. Your normal review and your normal CI take it from there.

Built to be reviewed

Kandryn opens pull requests and never merges them. A security scan of the committed change posts a status check your branch rules can require before anyone can merge, and every action is written to an audit log your admins can read.

See how Kandryn is governed →

See it run on one of your own tickets.

A walkthrough on a real work item from your board — not a canned recording.

Book a walkthrough