Skip to content

[refactor] Objective-mapping constants are dead code and contradict the live default mapping #52811

Description

@github-actions

Overview

Semantic function clustering analysis of the selected package slice (pkg/github, pkg/githubapi — 3 non-test Go files, 12 functions/methods). The dominant finding is not scattered helpers but a dead constants file whose values silently contradict the live default mapping it claims to mirror.

Metric Count
Files analyzed 3
Functions/methods cataloged 12
Clusters identified 4
Outliers found 1
Dead/divergent constants 56
Duplicate logic sites 6

Key issues

1. label_objective_mapping_constants.go is entirely unreferenced by production code — and diverges from DefaultObjectiveMapping()

All 28 ObjectiveLabel* and 28 ObjectiveValue* constants have zero production references. The only consumer is pkg/github/spec_test.go, which asserts them tautologically (ObjectiveValueCritical == 100 against a hardcoded 100) — so the test cannot detect drift.

The file header (label_objective_mapping_constants.go:5) states: "keep these values in sync with DefaultObjectiveMapping". They are not in sync. Six values contradict each other:

Label Constants file DefaultObjectiveMapping()
security-fix 70 75
copilot-opt 75 50
high-priority 35 50
p1 35 50
medium-priority 20 25
p2 20 25

A further 11 constants define scores for labels absent from the default mapping entirely — including bug (60), the highest-valued of the group: testing, reliability, workflow, engine, mcp, actions, cli, bug, lint-monster, dependencies, enhancement.

The practical effect: the constants file reads as the documented scoring policy, but LoadObjectiveMapping() never consults it. Anyone updating a constant to retune scoring changes nothing at runtime.

2. MultiLabelLogic* constants are ignored by the function they describe

MultiLabelLogicMax / Sum / First are declared at label_objective_mapping_constants.go:136-140, but ComputeObjectiveValue switches on raw string literals instead (label_objective_mapping.go:62,66,69). These constants are referenced by spec_test.go, so the test and the implementation agree only by coincidence of matching string values.

Remaining findings — duplication, outlier, and stdlib opportunities

3. Repeated normalize-and-lookup (4 sites)

The idiom strings.ToLower(strings.TrimSpace(label)) followed by an om.LabelToValue lookup appears four times in label_objective_mapping.go:

  • ComputeObjectiveValue:49-50
  • computeValueFirst:94-95
  • FilterObjectiveLabels:200-201
  • HasObjectiveLabel:233-234

Extracting func (om *ObjectiveMapping) lookup(label string) (int, bool) collapses all four and makes the normalization rule single-sourced — relevant because normalization semantics are part of the public contract (spec_test.go tests " BUG ").

4. githubapi.ClientOptions helper bypassed by two call sites

pkg/githubapi/options.go:9 exists to apply constants.DefaultHTTPClientTimeout, but has only one production caller (pkg/cli/update_check.go:236). Two other sites hand-roll the identical construction:

  • pkg/parser/remote_client.go:30-33
  • pkg/cli/secret_set_command.go:126-131

Both guard Host behind an if host != "", which is equivalent to passing it straight through since the empty string is the zero value — so both can call the helper directly. (The api.ClientOptions literals in pkg/workflow/repository_features_validation.go:289,343 are not candidates: they set EnableCache/CacheTTL, which the helper's signature does not express. Worth noting separately that those two omit the default timeout altogether.)

5. Hand-rolled stdlib equivalents

slices is already imported (label_objective_mapping.go:8) and the module targets Go 1.26:

  • computeValueMax:110-119 reimplements slices.Max.
  • GetAllLabels:243-248 builds-then-sorts where slices.Sorted(maps.Keys(...)) applies.

6. Outlier: LoadObjectiveMapping sits in a pure-semantics file

label_objective_mapping.go:148-189 performs env-var reading, filesystem access, and JSON decoding (os, encoding/json, path/filepath) inside a file otherwise dedicated to scoring semantics. Its three-tier precedence logic and error paths account for roughly a quarter of the file. Moving it to label_objective_mapping_config.go would leave the mapping file as pure, easily-testable computation.

Cluster analysis

Cluster 1 — Value computation (ComputeObjectiveValue, computeValueSum, computeValueFirst, computeValueMax)
Well organized. The dispatch-to-strategy split is clean and each helper is single-purpose. ✓

Cluster 2 — Label querying (FilterObjectiveLabels, HasObjectiveLabel, GetAllLabels)
Correctly colocated, but shares the duplicated normalization noted in finding 3.

Cluster 3 — Configuration/defaults (DefaultObjectiveMapping, LoadObjectiveMapping)
The outlier cluster — mixes I/O with the semantics file (finding 6), and DefaultObjectiveMapping duplicates the constants file's intent (finding 1).

Cluster 4 — Serialization (MarshalJSON, String)
Standard Go idioms, appropriately placed. ✓

pkg/githubapi/options.go is a single-function file with a clear purpose; its problem is under-adoption, not organization.

Next actions

  • Decide the source of truth for objective scores. Either build DefaultObjectiveMapping()'s map from the constants, or delete label_objective_mapping_constants.go along with the tautological assertions in spec_test.go. The current state — two contradicting tables, one of which is dead — is the worst option.
  • Reconcile the 6 divergent values and decide whether the 11 unmapped labels (notably bug) belong in the default mapping.
  • Replace the raw "max"/"sum"/"first" literals in ComputeObjectiveValue with the MultiLabelLogic* constants.
  • Extract the normalize-and-lookup helper (4 call sites).
  • Route pkg/parser/remote_client.go and pkg/cli/secret_set_command.go through githubapi.ClientOptions.
  • Optional: adopt slices.Max / slices.Sorted, and split LoadObjectiveMapping into a config file.

Detection method: Serena-assisted symbol inventory plus reference-count verification across all .go files. Every "unused" claim above was confirmed by whole-repo grep, not inferred from the package slice.

Generated by 🔧 Semantic Function Refactoring · sonnet46 · 174.1 AIC · ⌖ 20.2 AIC · ⊞ 9.6K ·

  • expires on Aug 16, 2026, 6:43 PM UTC-08:00

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions