diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index f3ce10c..60bfc1c 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -297,7 +297,7 @@ jobs: .toLowerCase() .replace(/\.rs$/g, "") .replace(/[^a-z0-9_-]+/g, "-") - .replace(/^-+|-+$/g, "") + .replace(/^[-_]+|[-_]+$/g, "") .slice(0, 40); } @@ -378,44 +378,36 @@ jobs: return refined; } - function compactNoisyModuleLabels(labels) { - const noisyPrefixes = new Set(["tool", "provider", "channel"]); + function compactModuleLabels(labels) { const groupedSegments = new Map(); - const compacted = new Set(); + const compactedModuleLabels = new Set(); const forcePathPrefixes = new Set(); for (const label of labels) { const parsed = parseModuleLabel(label); - if (!parsed) continue; + if (!parsed) { + compactedModuleLabels.add(label); + continue; + } if (!groupedSegments.has(parsed.prefix)) { groupedSegments.set(parsed.prefix, new Set()); } groupedSegments.get(parsed.prefix).add(parsed.segment); } - for (const label of labels) { - const parsed = parseModuleLabel(label); - if (!parsed) continue; - if (!noisyPrefixes.has(parsed.prefix)) { - compacted.add(label); - } - } - for (const [prefix, segments] of groupedSegments) { - if (!noisyPrefixes.has(prefix)) continue; + const uniqueSegments = [...new Set([...segments].filter(Boolean))]; + if (uniqueSegments.length === 0) continue; - const specificSegments = [...segments].filter((segment) => segment !== "core"); - const uniqueSpecificSegments = [...new Set(specificSegments)]; - - if (uniqueSpecificSegments.length === 1) { - compacted.add(`${prefix}:${uniqueSpecificSegments[0]}`); + if (uniqueSegments.length === 1) { + compactedModuleLabels.add(`${prefix}:${uniqueSegments[0]}`); } else { forcePathPrefixes.add(prefix); } } return { - moduleLabels: compacted, + moduleLabels: compactedModuleLabels, forcePathPrefixes, }; } @@ -560,7 +552,7 @@ jobs: } const refinedModuleLabels = refineModuleLabels(detectedModuleLabels); - const compactedModuleState = compactNoisyModuleLabels(refinedModuleLabels); + const compactedModuleState = compactModuleLabels(refinedModuleLabels); const selectedModuleLabels = compactedModuleState.moduleLabels; const forcePathPrefixes = compactedModuleState.forcePathPrefixes; const modulePrefixesWithLabels = new Set( diff --git a/docs/ci-map.md b/docs/ci-map.md index d3880b5..3b4a7bc 100644 --- a/docs/ci-map.md +++ b/docs/ci-map.md @@ -31,7 +31,7 @@ Merge-blocking checks should stay small and deterministic. Optional checks are u - Additional behavior: label descriptions are auto-managed as hover tooltips to explain each auto-judgment rule - Additional behavior: provider-related keywords in provider/config/onboard/integration changes are promoted to `provider:*` labels (for example `provider:kimi`, `provider:deepseek`) - Additional behavior: hierarchical de-duplication keeps only the most specific scope labels (for example `tool:composio` suppresses `tool:core` and `tool`) - - Additional behavior: noisy namespaces (`tool`, `provider`, `channel`) are compacted — one specific module keeps `prefix:component`; multiple specifics collapse to just `prefix` + - Additional behavior: module namespaces are compacted — one specific module keeps `prefix:component`; multiple specifics collapse to just `prefix` - Additional behavior: applies contributor tiers on PRs by merged PR count (`experienced` >=10, `principal` >=20, `distinguished` >=50) - Additional behavior: final label set is priority-sorted (`risk:*` first, then `size:*`, then contributor tier, then module/path labels) - Additional behavior: managed label colors follow display order to produce a smooth left-to-right gradient when many labels are present diff --git a/docs/pr-workflow.md b/docs/pr-workflow.md index b2cb4ea..9e46b9f 100644 --- a/docs/pr-workflow.md +++ b/docs/pr-workflow.md @@ -50,7 +50,7 @@ Maintain these branch protection rules on `main`: - Contributor opens PR with full `.github/pull_request_template.md`. - `PR Labeler` applies scope/path labels + size labels + risk labels + module labels (for example `channel:telegram`, `provider:kimi`, `tool:shell`) and contributor tiers by merged PR count (`experienced` >=10, `principal` >=20, `distinguished` >=50), while de-duplicating less-specific scope labels when a more specific module label is present. -- For `tool` / `provider` / `channel`, module labels are compacted to reduce noise: one specific module keeps `prefix:component`, but multiple specifics collapse to the base scope label. +- For all module prefixes, module labels are compacted to reduce noise: one specific module keeps `prefix:component`, but multiple specifics collapse to the base scope label `prefix`. - Label ordering is priority-first: `risk:*` -> `size:*` -> contributor tier -> module/path labels. - Hovering a label in GitHub shows its auto-managed description (rule/threshold summary). - Managed label colors are arranged by display order to create a smooth gradient across long label rows.