Skip to content

GitHub Issues standard

Standard scope

Applies to: All HCS-governed GitHub repos with Issues enabled (app-solution orgs, AzureLocal, thisismydemo, Hybrid Cloud Solutions, etc.) — not TierPoint (GitLab) Domain: github-issues Status: Active

This standard governs how GitHub's native issue taxonomy is used across the estate — issue types, issue fields, and labels — and the one thing we add on top: the roadmap marker. It exists so we don't reinvent what GitHub already ships. See work-item-sync.md for how these connect to ADO, and work-items.md for ADO-side authoring rules.

Two-standard split — read this before triaging or authoring an issue:

  • User-submitted issues (anyone files a Bug or Feature-request) — we don't control how they're written. This standard defines only how we triage them: type, priority, effort, labels. Do not reject an issue for poor writing; triage it and, if accepted, let the mirrored ADO item be the well-authored record.
  • Items we author and sync (the ADO→GitHub roadmap projection, and any ADO-originated GitHub issue) — these do have an authoring bar: they must follow the ADO User-Story/Feature authoring rules in work-items.md (title/description/AC), carry ado-managed, and be locked.

Issue types — use the GitHub-native defaults

GitHub ships three default org-level issue types. Use them as-is. Do not create custom types.

TypeUse when
BugA defect — something is broken. GitHub is master (see work-item-sync.md Flow 1).
FeatureA feature request or roadmap candidate. GitHub is master until approved, then ADO becomes master and the approved item projects back down (Flow 2).
TaskA chore / work unit. Rare for external-facing repos; mostly internal.

If an issue type is disabled at the org level, re-enable it — do not work around a disabled type with a label.


Issue fields — use the GitHub-native defaults, not label workarounds

Every org gets four preconfigured, typed fields. Use these instead of priority/* or effort/* labels.

FieldTypeMaps to ADOPinned to
Prioritysingle-selectPriority 1–4Bug, Feature
Effortsingle-select/numberStory Points / EffortBug, Feature
Start datedateschedule alignmentFeature
Target datedateschedule alignmentFeature

Configure these once per org (Part E1 of the pmo plan); do not redefine them per repo.

The one field we add: Delivery Stage

A custom org-level single-select field, used only on the ADO→GitHub roadmap projection (Flow 2):

Backlog → Approved → Roadmap → In-Progress → Shipped

This is what makes the roadmap queryable/reportable instead of just tag-present/absent. It is set and updated only by the sync bot — never manually.


Labels — minimal, workflow-only

Labels are not used for type or priority anymore (the native type + fields above cover those). The full reserved label set:

LabelMeaningSet by
needs-triageUn-triaged intake — new issue, not yet reviewedanyone filing
ado-trackedIssue has a linked ADO work item (Flow 1)sync bot
in-progressLinked ADO item is actively being worked (Flow 1)sync bot
resolvedLinked ADO item resolved, pending close (Flow 1)sync bot
wont-fixLinked ADO item closed as won't-fix (Flow 1)sync bot
roadmapApproved Feature projected from ADO — on the public roadmap (Flow 2)sync bot
ado-managedLock marker — this issue is a bot-owned ADO projection; do not edit (Flow 2)sync bot
cross-repoAffects multiple reposanyone

Do not add new labels for type/priority/effort — use the native fields. If a genuinely new workflow label is needed, add it to this table via a PR first.


Enforcement — "no one can edit that tag"

GitHub has no hard read-only-issue primitive. The accepted pattern, used here:

  1. The ADO→GitHub projection (Flow 2) is created/updated only by the sync bot identity (a dedicated GitHub App or fine-grained PAT — never a personal token).
  2. The projected issue is locked (lock conversation) immediately after creation/update.
  3. A scheduled reconcile job diffs the projection against ADO state; any manual edit, unlock, or label change is reverted and the issue is re-locked.
  4. ado-managed is the human-visible signal — anyone looking at the issue sees it's bot-owned before they try to edit it.

Roadmap surface — GitHub Projects (v2) board

The roadmap lives as an org-level GitHub Projects (v2) board, populated by the Flow 2 sync (projected issues + their Delivery Stage field). No ROADMAP.md file is generated.

Any web page (platform.hybridsolutions.cloud, product sites) reads the live roadmap via the Projects v2 GraphQL API — query the project's items and the Delivery Stage field, fetched at build time or on a schedule, rendered as a normal page. This keeps one source of visual truth (the board) instead of a board plus a separately-synced markdown file.


Issue templates

Repos onboarded with the intake layer get .github/ISSUE_TEMPLATE/{bug,feature,task}.yml, bound to the native types above (templates/.github/ISSUE_TEMPLATE/ in this repo — stamped by the onboarding scaffolder). Do not hand-author bespoke templates per repo; extend the shared templates via a PR to this repo if a field is missing.


Remote agents

Issue intake is designed to be agent-agnostic — either GitHub's native Copilot coding agent or a Claude-Code-via-Action workflow can be assigned to work a labeled issue. No agent is wired in by this standard; that's a separate, later decision. Don't build agent-specific coupling into the templates or labels above.


Reference — ADO ↔ GitHub mapping

GitHub (native)ADO
Issue type BugBug work item
Issue type Feature (user-submitted request)mirrored up as a Feature candidate; on approval becomes ADO Feature (master)
Issue type TaskTask work item
Field PriorityPriority 1–4
Field EffortStory Points / Effort
Label roadmap + lockedADO Feature on the roadmap (ADO is master, GitHub is read-only projection)
Label ado-managedany ADO-mastered item projected to GitHub
Field Delivery StageFeature's roadmap state (Backlog → Approved → Roadmap → In-Progress → Shipped)

Copyright © Hybrid Cloud Solutions LLC — Kristopher Turner