A MODERN BOARD FOR AI-FIRST ENGINEERING TEAMS

First, Claude and Cursor made every developer faster. Now, Trundle does it for entire engineering teams.

No card required · Simple signup · No gotchas

A MODERN BOARD FOR AI-FIRST ENGINEERING TEAMS

First, Claude and Cursor made every developer faster. Now, Trundle does it for entire engineering teams.

No card required · Simple signup · No gotchas

A MODERN BOARD FOR AI-FIRST ENGINEERING TEAMS

First, Claude and Cursor made every developer faster. Now, Trundle does it for entire engineering teams.

No card required · Simple signup · No gotchas

Orchestrate a team of agents

AGENTS BUILT INTO THE WORKFLOW

Built-in AI agents pick up work when needed, so you rely less on expensive Claude usage.

CONNECTED TO YOUR TOOL STACK

Connect Slack, GitHub and the tools your team already uses.

FITS THE WAY YOUR TEAM WORKS

Easy to set up and flexible enough to fit your team.

Create tickets from any chat thread

Mention Trundle in any thread and the ticket writes itself into the backlog, with the conversation attached as context.

Northwind
Threads
Drafts & sent
Channels
announcements
eng-general
eng-releases
eng-frontend
incidents
design-review
Direct messages
Priya Raman
Tom Beckett
Marta Lindqvist
Daniel Okoye
Apps
Trundle
eng-general18
MessagesFilesPins
Today
Priya Raman
Priya Raman09:12
main is red again. Same auth spec as Tuesday, passes on a re-run.
Tom Beckett
Tom Beckett09:14
Third time this week. It’s session_refresh_spec — the one that asserts the token rotates before the old one expires.
Marta Lindqvist
Marta Lindqvist09:17
The spec freezes the clock at the top and the refresh path reads Time.now directly instead of the injected clock, so under load the two drift apart and the assertion lands on the wrong side of the boundary.
Daniel Okoye
Daniel Okoye09:21
That tracks. It only goes red when CI is busy, never locally. I’ve re-run it enough times to be sure it’s not the token logic.
Priya Raman
Priya Raman09:23
Can we route the refresh path through the injected clock and stop everyone re-running the build? People have started ignoring red on main.
BIS🔗</>
@Trundle can you make a ticket from this thread?
😊@
Thread
Marc Hinton
Marc HintonToday at 09:24
@Trundle can you make a ticket from this thread?
1 reply
TrundleApp09:24
Sure thing, let me work on that for you now.
Reading the thread
BI🔗
Reply…
😊
Also send to #eng-general
Marc Hinton

Platform / Backlog

Auth, CI and the things nobody owns.

TicketsKnowledgeBuildsAnalytics

7 tickets · Last updated 14 minutes ago

  • PlatformTR-1551

    Drop Node 18 from the CI matrix now that 22 is the default

    Daniel Okoye
  • PlatformTR-1550

    Settings page takes ~4s to first paint for orgs over 500 seats

    Tom Beckett
  • PlatformTR-1549

    Add a health endpoint the load balancer can actually read

    Marta Lindqvist
  • PlatformTR-1548

    Bulk import silently skips rows with a trailing comma

    Priya Raman
  • PlatformTR-1547

    Replace the deprecated crypto.createCipher calls before the Node bump

    Tom Beckett
  • PlatformTR-1546

    Search returns archived projects when the filter is left empty

    Priya Raman
  • PlatformTR-1545

    Split the 900-line UserService into something reviewable

    Daniel Okoye

Write every ticket against your own docs

Attach what the team already wrote and every ticket in the project is written against it, so the agents build from your rules rather than their guesses.

You

Design system / Knowledge

Components, tokens and the front end that uses them.

TicketsKnowledgeBuildsAnalytics
Knowledge BaseSelect documents to attach · 0 of 3

Attaching uploaded documents to projects and tickets means agents are held to your expected implementation, brand, coding standards, design or roadmap.

Now on all 12 tickets in Design system
Design systemTR-1560

Replace the legacy button across Settings

Codie
Design systemTR-1561

Focus states on every form input

Codie
Design systemTR-1562

Fix contrast on the muted text token

Codie

Review work before anything merges

Dev, review and QA are three separate agents, and the board shows every handover between them. Your team stays in the loop and keeps the final say on what merges.

Priya Nair

Sprint 24 / Board

Saved cards live, and main green again.

BoardTickets 13Action ItemsAnalyticsSettingsEnds in 3 days
In Progress4
Pending Review4
In Review3
Pending QA0
In QA2
Growth WebTR-0431

Rewrite the pricing page copy for the new tiers

Billing CoreTR-0440

Show saved cards in the account area

Cloning repo
Onboarding FunnelTR-0426

Import Jira epics as projects

PlatformTR-0398

Cache repo setup between dev runs

Writing code
Billing CoreTR-0405

Stop retrying a Stripe webhook after the fourth failure

Queued
PlatformTR-0384

Trim stale branches after a pull request merges

Queued
Mobile AppTR-0372

Fix the crash on tablet rotation

Queued
Search & IndexTR-0389

Rate-limit the public search endpoint

Queued
Billing CoreTR-0412

Let customers save a card at checkout

Finishing up
Mobile AppTR-0377

Deep links into a single ticket

Reviewing
Search & IndexTR-0370

Board filters remember your last view

Finishing up
Onboarding FunnelTR-0361

Onboarding checklist for new workspaces

Build succeeded
Lifecycle MessagingTR-0355

A/B test subject lines from the campaign editor

QA Checks
You flagged that you wanted to test this ticket yourself — click it to begin

Follow the work with one clear recap

Trundle keeps dev, review and QA recaps on the ticket, so decisions, progress and next steps are easier to find.

Payments/PROJ-482
Activity
AllCommentsHistoryWork log
Newest first
PRAdd a comment…
ML
Marta Lindqvist16 Jul 2026, 16:03

Can someone write this up somewhere? I’ve lost the thread on why we’re not using the queue.

LikeReply
DO
Daniel Okoye16 Jul 2026, 11:48

For the record: the 500 in staging was a stale env var, not this change.

LikeReply
SM
Sofia Marino16 Jul 2026, 09:20

Didn’t add the success metric, it’s blocked on the analytics pipeline accepting custom counters.

LikeReply
AC
Alex Chen15 Jul 2026, 14:07

Only exercised GBP and USD. EUR takes a different rounding path, someone needs to check it.

LikeReply
ML
Marta Lindqvist15 Jul 2026, 10:55

Flag is billing.reconcile_v2, defaulted off. Ops flip it after the backfill, not before.

LikeReply
PR
Priya Raman15 Jul 2026, 09:30

Leaving the legacy status column in place, the finance export still reads it.

LikeReply
DO
Daniel Okoye15 Jul 2026, 08:12

Skipped the down migration — invoice_events is ~40M rows and the rollback would lock it for minutes.

LikeReply
TB
Tom Beckett14 Jul 2026, 15:44

We tried a queued job first. The follow-up webhook can land before the job runs, so it’s synchronous now.

LikeReply
SM
Sofia Marino14 Jul 2026, 13:28

Shared cache gets evicted every ~5 min in prod, so reconciliation state went into Redis with its own TTL.

LikeReply
AC
Alex Chen14 Jul 2026, 11:15

Retry count is 3 on purpose, it matches Stripe’s idempotency window. Please don’t lower it.

LikeReply
TB
Tom Beckett14 Jul 2026, 10:02

Deliberately not touching BillingService in here. That refactor is PROJ-501, keep them apart.

LikeReply
PR
Priya Raman14 Jul 2026, 09:41

Going with optimistic locking on invoices rather than a row lock — we can’t hold a lock across the Stripe call.

LikeReply
TR-1549
AssigneeShare

Reconcile Stripe invoices with the ledger

Reconciled Stripe invoices without holding a database lock across the payment call.

What we did

Added a reconciliation path that claims an invoice with an optimistic version check, calls Stripe, then commits the outcome. Run state lives in Redis under its own TTL, so a shared-cache eviction can’t drop a run mid-flight. The whole path sits behind billing.reconcile_v2, defaulted off.

Changes

  • app/Billing/InvoiceReconciler.phpNew service. Claims an invoice with a version check, calls Stripe, writes the outcome back in a single transaction.
  • app/Repositories/InvoiceRepository.phpAdded claimForReconciliation() — the only place the version check is issued.
  • database/migrations/2026_07_14_101122_add_version_to_invoices.phpAdds invoices.version. No down migration: invoice_events is ~40M rows and the rollback would lock it.
  • config/billing.phpRegisters the billing.reconcile_v2 flag, off by default.

Considerations

  • Chose: Optimistic locking on invoices.version
    Instead of: A row lock held across the Stripe call
    The lock would be held for the full network round trip, blocking every other writer on that row.
  • Chose: Reconciling synchronously in the webhook handler
    Instead of: Dispatching a queued job
    The follow-up webhook can arrive before the job is picked up, which reorders events that have to stay ordered.
  • Chose: Retrying three times
    Instead of: Unbounded retries with backoff
    Stripe idempotency keys expire after 24h — retries past that window create a second charge instead of replaying the first.
  • Chose: Keeping the legacy status column
    Instead of: Dropping it as part of this ticket
    The finance export still reads it. Removing it is its own change with its own rollout.

Implications

  • invoices now carries a version column. Any writer that bypasses claimForReconciliation() will lose its update silently.
  • Nothing changes in production until ops enable billing.reconcile_v2 after the backfill.
  • This migration has to be rolled back by hand — there is no down path.
  • BillingService is untouched, so the refactor in PROJ-501 can still land independently.

Not done

  • EUR was not exercised. It takes a different rounding path in the Stripe response and needs its own pass.
  • The reconciliation success metric is not wired up; the analytics pipeline doesn’t accept custom counters yet.
  • No backfill for invoices created before this change — they stay on the legacy path until reconciled.

Benefits

  • Reconciliation no longer blocks other writers on the invoice row.
  • A cache eviction mid-run can’t leave an invoice half-reconciled.
  • The rollout is reversible at the flag, without a deploy.

How Trundle works

HOW WE HANDLE YOUR CODE

Your code stays private

Your repository is cloned into an isolated environment for the length of a job, then destroyed when the job ends. Nothing persists on Trundle's servers, nothing is used to train models, and no one on our team can read it. Every change lands on a feature branch in your repository, where your team decides what merges.

ONLY WHAT THE TASK NEEDS
NEVER SEEN BY OUR TEAM
AUDIT TRAIL ON EVERY ACTION
NEVER USED TO TRAIN MODELS
Trundle
Trundle
Trundle
Trundle

Work moves better when everyone can see where it is going.

Trundle

Work moves better when everyone can see where it is going.

Trundle

Work moves better when everyone can see where it is going.