Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 65 additions & 25 deletions .agents/scripts/issue-sync-helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,30 @@ extract_file_summary() {
# Tag to Label Mapping
# =============================================================================

# Map TODO.md #tags to GitHub labels
# Create a label on GitHub if it doesn't exist (t295: label passthrough)
# Uses gh label create --force to ensure label exists with consistent color
create_label_if_needed() {
local label_name="$1"
local repo_slug="$2"

if [[ -z "$label_name" || -z "$repo_slug" ]]; then
return 1
fi

# Use --force to create or update the label (idempotent)
# Assign a consistent color based on label name hash for visual consistency
local color
color=$(echo -n "$label_name" | md5sum | cut -c1-6)
Comment on lines +529 to +530
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

md5sum is a GNU coreutils command and is not available on macOS by default, which uses md5. This could lead to portability issues. The style guide emphasizes portability with the sed_inplace wrapper (line 20). To ensure cross-platform compatibility, it would be best to handle both cases, for example by checking for the command's existence.

Suggested change
local color
color=$(echo -n "$label_name" | md5sum | cut -c1-6)
local color
if command -v md5sum >/dev/null; then
color=$(echo -n "$label_name" | md5sum | cut -c1-6)
else
color=$(echo -n "$label_name" | md5 | cut -c1-6)
fi
References
  1. The style guide recommends using wrappers like sed_inplace for macOS/Linux portability, suggesting that cross-platform compatibility is a concern. (link)


gh label create "$label_name" --repo "$repo_slug" --color "$color" --force 2>/dev/null || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of 2>/dev/null here suppresses all error messages from gh label create. This violates the repository style guide (line 50), which states that 2>/dev/null should not be used for blanket suppression. While --force makes the command idempotent for existing labels, other errors (like authentication failures or an invalid repository slug) will be silently ignored, making debugging difficult. The || true already prevents the script from exiting on failure.

Suggested change
gh label create "$label_name" --repo "$repo_slug" --color "$color" --force 2>/dev/null || true
gh label create "$label_name" --repo "$repo_slug" --color "$color" --force || true
References
  1. The style guide states that 2>/dev/null is acceptable only when redirecting to log files, and not for blanket suppression of errors. (link)

return 0
}

# Map TODO.md #tags to GitHub labels (t295: passthrough with on-the-fly creation)
# Now creates labels on-the-fly instead of silently dropping unknown tags
map_tags_to_labels() {
local tags="$1"
local repo_slug="${2:-}"

if [[ -z "$tags" ]]; then
return 0
Expand All @@ -526,29 +547,14 @@ map_tags_to_labels() {
local IFS=','
for tag in $tags; do
tag="${tag#\#}" # Remove # prefix if present
case "$tag" in
plan) labels="${labels:+$labels,}plan" ;;
bugfix|bug) labels="${labels:+$labels,}bug" ;;
enhancement|feat|feature) labels="${labels:+$labels,}enhancement" ;;
security) labels="${labels:+$labels,}security" ;;
git|sync) labels="${labels:+$labels,}git" ;;
orchestration) labels="${labels:+$labels,}orchestration" ;;
plugins) labels="${labels:+$labels,}plugins" ;;
architecture) labels="${labels:+$labels,}architecture" ;;
voice) labels="${labels:+$labels,}voice" ;;
tools) labels="${labels:+$labels,}tools" ;;
seo) labels="${labels:+$labels,}seo" ;;
research) labels="${labels:+$labels,}research" ;;
agents) labels="${labels:+$labels,}agents" ;;
browser) labels="${labels:+$labels,}browser" ;;
mobile) labels="${labels:+$labels,}mobile" ;;
content) labels="${labels:+$labels,}content" ;;
accounting) labels="${labels:+$labels,}accounting" ;;
dashboard) labels="${labels:+$labels,}dashboard" ;;
multi-model) labels="${labels:+$labels,}multi-model" ;;
quality|hardening) labels="${labels:+$labels,}quality" ;;
# Tags that don't map to labels are silently skipped
esac

# Create the label if repo_slug is provided (during issue creation)
if [[ -n "$repo_slug" ]]; then
create_label_if_needed "$tag" "$repo_slug"
fi

# Add to labels list (passthrough: all tags become labels)
labels="${labels:+$labels,}$tag"
done

# Deduplicate
Expand Down Expand Up @@ -809,7 +815,7 @@ cmd_push() {

local title="${task_id}: ${description}"
local labels
labels=$(map_tags_to_labels "$tags")
labels=$(map_tags_to_labels "$tags" "$repo_slug")

# Compose rich body
local body
Expand Down Expand Up @@ -921,15 +927,49 @@ cmd_enrich() {
local body
body=$(compose_issue_body "$task_id" "$project_root")

# Extract tags from task line for label sync (t295)
local parsed
parsed=$(parse_task_line "$task_line")
local tags
tags=$(echo "$parsed" | grep '^tags=' | cut -d= -f2-)

if [[ "$DRY_RUN" == "true" ]]; then
print_info "[DRY-RUN] Would enrich #$issue_number ($task_id)"
if [[ -n "$tags" ]]; then
local labels
labels=$(map_tags_to_labels "$tags" "$repo_slug")
print_info " Labels: $labels"
fi
enriched=$((enriched + 1))
continue
fi

# Update the issue body
if gh issue edit "$issue_number" --repo "$repo_slug" --body "$body" 2>/dev/null; then
print_success "Enriched #$issue_number ($task_id)"

# Sync labels from TODO.md tags to GitHub issue (t295: label passthrough)
if [[ -n "$tags" ]]; then
local labels
labels=$(map_tags_to_labels "$tags" "$repo_slug")
if [[ -n "$labels" ]]; then
# Add status label if not already present
local status_label="status:available"
if echo "$task_line" | grep -qE 'assignee:'; then
status_label="status:claimed"
fi
if [[ -n "$labels" ]]; then
labels="${labels},${status_label}"
else
labels="$status_label"
fi
Comment on lines +961 to +965
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The if [[ -n "$labels" ]] check on line 961 is redundant because it's nested inside an identical check on line 955. This makes the else block on line 964 unreachable. The code can be simplified by removing the inner conditional.

Suggested change
if [[ -n "$labels" ]]; then
labels="${labels},${status_label}"
else
labels="$status_label"
fi
labels="${labels},${status_label}"

# Update issue labels
if gh issue edit "$issue_number" --repo "$repo_slug" --add-label "$labels" 2>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to a previous comment, the use of 2>/dev/null here suppresses potentially useful error messages from gh issue edit. This violates the repository style guide (line 50). If the command fails due to issues like invalid permissions or network problems, the error will be hidden, complicating troubleshooting. Since gh issue edit --add-label doesn't fail if labels already exist, simply checking the command's success in the if statement is sufficient.

Suggested change
if gh issue edit "$issue_number" --repo "$repo_slug" --add-label "$labels" 2>/dev/null; then
if gh issue edit "$issue_number" --repo "$repo_slug" --add-label "$labels"; then
References
  1. The style guide states that 2>/dev/null is acceptable only when redirecting to log files, and not for blanket suppression of errors. (link)

log_verbose "Synced labels to #$issue_number: $labels"
fi
fi
fi

enriched=$((enriched + 1))
else
print_error "Failed to enrich #$issue_number ($task_id)"
Expand Down