ADR-020: Human-Required Label Strategy
Status
Accepted - 2025-10-01
Context
Workflows create issues and pull requests that need human attention. The usual approach assigns them with the --assignee flag, which has several problems:
- Username resolution: the GraphQL API requires exact usernames, and an organization name cannot be assigned
- Dynamic context: workflows run under different triggering users and repository owners
- API failures: an invalid username fails the workflow with errors like "Could not resolve to a User with the login of 'organization-name'"
- Maintenance: hardcoded usernames go stale
- Template reuse: a template used across many repositories cannot carry a fixed assignee
The original implementation used patterns like:
--assignee "${{ github.repository_owner }}" # Organization name (invalid)
--assignee "hardcoded-username" # Brittle
These failures blocked automation.
Decision
Replace assignee-based task management with labels:
- No assignees: remove every
--assigneeflag from automated workflows human-requiredlabel: marks any item that needs a person to act- Label-based filtering: team members find work by filtering on labels
- Labels do not fail: no username resolution is involved
- Combinations: priority and category labels refine the queue
Core label
From .github/labels.json (managed by ADR-008):
Supporting labels
high-priority: urgent itemsconflict: merge conflicts requiring manual resolutionescalation: items that have exceeded the conflict SLAsync-failed: failed upstream synchronizationtemplate-sync-failed: failed template synchronization
Lifecycle labels (ADR-022)
upstream-sync: tracking issue for an upstream synchronizationcascade-active: cascade integration in progresscascade-blocked: cascade blocked by conflicts or validation failurecascade-failed: cascade failed; paired withhuman-requireduntil a person clears itcascade-escalated: conflict older than 48 hoursvalidated: integration completetemplate-sync: template update PRs and issues
Workflow pattern
Before:
ASSIGNEE="${{ github.actor }}"
if gh api users/"$ASSIGNEE" >/dev/null 2>&1; then
ASSIGNEE_FLAG="--assignee $ASSIGNEE"
else
ASSIGNEE_FLAG=""
fi
gh issue create --title "..." --body "..." --label "some-label" $ASSIGNEE_FLAG
After:
gh issue create \
--title "📥 Upstream Sync Ready for Review - $(date +%Y-%m-%d)" \
--body "$NOTIFICATION_BODY" \
--label "upstream-sync,human-required"
# Lifecycle update when the cascade starts
gh issue edit "$ISSUE_NUMBER" \
--remove-label "human-required" \
--add-label "cascade-active"
Where the label is used
sync.yml: tracking issueupstream-sync,human-required; failure issuesync-failed,human-requiredcascade.yml: conflict PRs and issues (conflict,cascade-blocked,high-priority,human-required), validation failures, held-upstream issues, and failure issues; the label is removed when the cascade starts and re-added on failurecascade-monitor.yml: escalation issues (escalation,high-priority,cascade-escalated,human-required); the recovery job treats the absence ofhuman-requiredon acascade-failedissue as the retry signalsync-template.yml: the label-configuration issue (human-required,template-sync); the template-sync PR itself carries onlytemplate-sync
Filtering
label:human-required # everything needing a person
label:human-required label:high-priority # urgent
label:human-required label:conflict # conflicts to resolve
label:upstream-sync label:human-required # sync awaiting merge and cascade trigger
label:upstream-sync label:cascade-active # integration in progress
label:upstream-sync label:cascade-blocked # blocked
Alternatives Considered
- Assignee validation with fallbacks: rejected; complex, still fails in edge cases, and adds API calls.
- Assignee from a repository variable: rejected; still requires a valid username and per-repository setup.
- External assignment service: rejected; extra infrastructure.
- Assignment plus labels: rejected; keeps the assignment failure mode.
Consequences
Nobody is assigned, so individual accountability depends on team discipline and there are no assignment notifications. Teams filter by label instead. In exchange, issue creation never fails on username resolution and the template works identically in every repository.
Related Decisions
- ADR-008: Centralized Label Management Strategy - Defines how labels are managed
- ADR-019: Cascade Monitor Pattern - Uses
human-requiredas the recovery signal - ADR-022: Issue Lifecycle Tracking Pattern - Defines lifecycle label usage