Quick answer: Pick one tool as the source of truth (your bug tracker). Mint a canonical ID for every bug. Every PR, commit, Slack thread, and design doc references the ID, never duplicates the bug details. Install a Slack unfurl bot and PR webhooks so the references resolve automatically to current status.

A senior engineer reads a Slack thread about “that physics crash from last week.” She checks GitHub and finds three PRs that mention “physics crash.” None of them link to the tracker. The tracker has four open crashes, two of which could match. Thirty minutes later she still doesn’t know whether the bug she’s about to start working on is already fixed. The fix is not another tool. It’s a discipline: one ID everywhere, one source of truth.

Pick the Canonical ID Format

Your bug tracker mints the IDs. Use a short prefix that’s easy to type and hard to confuse with other IDs. BUG-412, FOX-2103 (initials of the game), QA-88. Whatever you pick, stick to it — changing the prefix a year in leaves a long tail of references that no longer match.

Avoid collisions with your engine’s own numbering (Unity UUM- or Unreal UE-) and with anything that already means something in your engineering lingo. Your bots will run regexes on these, and a false positive (BUG- inside a URL or a file name) is annoying.

Set the One Rule

The rule is: if it relates to a bug, it references the bug’s canonical ID.

Anything that breaks the rule either goes through review and gets fixed or gets flagged by a bot. Over time the team internalizes the habit.

Bot Integrations That Earn Their Keep

Slack unfurl bot. When someone mentions BUG-412 in a channel, the bot replies with a small preview: title, current status, assignee, and a link. Readers don’t have to context-switch. Writing your own is a half-day of work against the Slack API — listen for message events, regex for BUG-\d+, call the tracker API, post a reply.

# Minimal Slack bot in Python (Bolt)
import re, requests
from slack_bolt import App

BUG_RE = re.compile(r"\bBUG-(\d+)\b")
app = App(token=SLACK_BOT_TOKEN)

@app.message(BUG_RE)
def unfurl(message, say):
    for m in BUG_RE.finditer(message["text"]):
        bug = requests.get(f"https://bugnet.io/api/bugs/BUG-{m.group(1)}").json()["data"]
        say(
            thread_ts=message["ts"],
            text=f"*{bug['id']}*: {bug['title']}\nStatus: {bug['status']}  Assignee: {bug['assignee']}"
        )

GitHub PR webhook. When a PR is opened or merged, parse the title for BUG-\d+ and tell the tracker. The tracker links the PR, which then appears as “Fix in progress” on the bug page. On merge, it auto-transitions to “awaiting QA.” The discipline is enforced by making the convenient path also the correct one.

Commit hook. Optional, but cheap. A pre-push hook warns when commits don’t reference a bug ID and the branch name doesn’t suggest a chore. It’s a nudge, not a block — hotfix branches bypass it.

One Source of Truth, Always

Every tool has a temptation to become the source of truth. Slack threads grow into rich histories that feel authoritative. PRs accumulate detailed debugging conversations. Google Docs fill with screenshots. Resist all of that.

The bug tracker carries the bug’s state over its whole life. Slack threads lock after 90 days. PRs close. Docs get forgotten. If the bug tracker doesn’t have the information, the information is gone. So: attach screenshots to the tracker, copy the key findings from the Slack thread back, and link out from the tracker to the PR — not the reverse.

What to Put Where

A quick reference to settle arguments:

Cleaning Up Drift

Even with rules, drift happens. A quarterly cleanup script helps:

The script doesn’t need to fix anything automatically. A Slack DM to the owner is usually enough. The value is visibility — the drift is the defect; the fix is the owner’s to make.

“The measure of a good tracker isn’t how many bugs are in it. It’s how often the question ‘what’s the status?’ can be answered in one link.”

Related Issues

For decision records that pair with links, see how to write a bug triage decision log. For picking the right tool to be that source of truth, see bug tracker comparison for indie developers.

One ID. One tool of record. Everything else links, nothing else owns.