← All articles

Shoring Up a Fresh Fork: Issue Templates, Discussions, and the API-vs-Manual Line

Development · September 4, 2026

Shoring Up a Fresh Fork: Issue Templates, Discussions, and the API-vs-Manual Line

The setup. A fresh GitHub fork — an actively-developed macOS port of a desktop-pet app — with no release artifact yet, a handful of inherited repository features, and a governance strategy (branching lanes, a triage lifecycle, a roadmap) still being codified. The goal: stand up the issue-reporting and discussion surfaces so contributors, when they arrive, land somewhere that reflects how this project actually works — rather than inheriting the fork-parent's habits.

This is the story of that cleanup: what we changed, why, and — the part that turned out to be most interesting — exactly where the boundary fell between what an automation can do over GitHub's API and what still requires a human at a web UI.


The starting problem: a fork inherits its parent's voice

A fork is born with its parent's settings. The inherited .github/ISSUE_TEMPLATE/ told the story of a different project:

Meanwhile, the project's own governance documents (VERSIONING.md, ROADMAP.md) described a triage lifecycle, a set of branch lanes, and a labels table — none of which the inherited forms referenced. The repo's *behavior* (what users see when they click "New Issue") was out of sync with its *documented intent* (how issues actually get triaged and fixed). Classic small-fork drift.

Aligning features to the dev cycle

Issue templates. We rewrote bug_report.yml to match the report template in ROADMAP.md: summary, reproduction steps, expected-vs-actual, environment fields (macOS version, app version/build), an optional classification guess, and localization impact. Two new forms were added:

Labels. The repo came with GitHub's default set plus an upstream courtesy label (accessibility) — ten in all, half of which the workflow would never use. We trimmed to the labels the governance documents actually reference:

bug · hotfix · enhancement · localization · macos-version · docs · duplicate · needs-info

Six of those are the triage-lane labels from VERSIONING.md; needs-info is the "awaiting more info from the reporter" state from the triage lifecycle; duplicate survives purely because every issue tracker needs it. Everything else — invalid, wontfix, question, good first issue, help wanted, accessibility, documentation — went away. Not because they're bad labels, but because a label that maps to no workflow action is just decoration, and decoration is how trackers get confusing. Keep the labels the workflow actually uses; let the forms default-apply one label each and leave classification to the maintainer at triage.

Discussions. With question deleted from the label set and blank issues disabled, a contributor with a question had nowhere legitimate to go — they'd be forced into the bug form with required fields. So we enabled GitHub Discussions as the planned pressure valve: Q&A, help, and rough ideas live there; only confirmed defects and roadmap-backed items become issues. The route was made explicit everywhere a contributor would land — the "New Issue" page (contact_links in config.yml), the README (all three languages), CONTRIBUTING, and the governance docs.

Staying on the vision

The most deliberate part was deciding what *not* to do.

The API-vs-manual line

This was the most instructive part: what could be automated, and what had to be done by hand.

Via API (all scripted):

Manual (no API, no workaround):

The boundary lesson: labels, forms, docs, and merge workflow are all API-addressable; anything that lives in Discussions' own UI (categories, pinned posts, replies) is human-only. The clean partition is to route anything that needs action into issues, where the automated lifecycle can take over.

The fork-discoverability footnote

A curious coda: the repo doesn't show up for a generic search of its own name. That turned out to be GitHub's documented rule — forks are excluded from default repository search unless they out-star their parent. The fork has 1 star against its parent's 5, so it's invisible to the default search, full stop; age is irrelevant. It *is* findable with qualified search (fork:true, user:...), and the zero-star *non-fork* on page 2 of the results is consistent — the fork rule doesn't apply to non-forks. Nothing to fix; it's just how a deliberate, un-promoted fork behaves, and for this experiment it's exactly what we wanted.


*Written as part of an experiment in doing development with an AI assistant: what can be delegated end-to-end over the API, and which corners of GitHub still need a human.*