Skip to content

Commit 8d2c890

Browse files
fix(features): address resolver review feedback
Keep legacy string APIs compatible, seed feature state from each inventory's checker, persist caching for stdio calls, and fail closed for empty undeclared flags. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1e4a1ca6-53f7-4158-af22-35d2448d0b13
1 parent a87351e commit 8d2c890

18 files changed

Lines changed: 149 additions & 114 deletions

‎cmd/github-mcp-server/feature_flag_docs.go‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func generateFeatureFlagsDocs(docsPath string) error {
3333
// whose registration or definition differs from the default user experience.
3434
// Each affected tool is printed with its full schema using the same writer
3535
// used by the README so the output style stays consistent.
36-
func generateFlaggedToolsDoc(flags []inventory.FeatureFlag, emptyMessage string) string {
36+
func generateFlaggedToolsDoc(flags []string, emptyMessage string) string {
3737
t, _ := translations.TranslationHelper()
3838
defaultTools := indexToolsByName(buildInventoryWithFlags(t, nil).ToolsForRegistration(context.Background()))
3939

@@ -73,8 +73,8 @@ func generateFlaggedToolsDoc(flags []inventory.FeatureFlag, emptyMessage string)
7373
// differs from the default-flagged inventory when only the given flag is on,
7474
// plus tools that exist only in the flag-on inventory. Results are sorted by
7575
// tool name.
76-
func flaggedToolDiff(t translations.TranslationHelperFunc, flag inventory.FeatureFlag, defaultTools map[string]inventory.ServerTool) []inventory.ServerTool {
77-
flagTools := buildInventoryWithFlags(t, map[inventory.FeatureFlag]bool{flag: true}).ToolsForRegistration(context.Background())
76+
func flaggedToolDiff(t translations.TranslationHelperFunc, flag string, defaultTools map[string]inventory.ServerTool) []inventory.ServerTool {
77+
flagTools := buildInventoryWithFlags(t, map[string]bool{flag: true}).ToolsForRegistration(context.Background())
7878

7979
out := make([]inventory.ServerTool, 0)
8080
seen := make(map[string]struct{}, len(flagTools))
@@ -99,9 +99,9 @@ func flaggedToolDiff(t translations.TranslationHelperFunc, flag inventory.Featur
9999
// buildInventoryWithFlags constructs an inventory whose feature checker treats
100100
// the given flags as enabled and every other flag as disabled. Passing nil
101101
// produces the default-flagged inventory.
102-
func buildInventoryWithFlags(t translations.TranslationHelperFunc, enabled map[inventory.FeatureFlag]bool) *inventory.Inventory {
102+
func buildInventoryWithFlags(t translations.TranslationHelperFunc, enabled map[string]bool) *inventory.Inventory {
103103
checker := func(_ context.Context, flag inventory.FeatureFlag) (bool, error) {
104-
return enabled[flag], nil
104+
return enabled[string(flag)], nil
105105
}
106106
inv, _ := github.NewInventory(t).
107107
WithToolsets([]string{"all"}).

‎internal/ghmcp/server.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,9 +435,9 @@ func RunStdioServer(cfg StdioServerConfig) error {
435435
// using the centralized ResolveFeatureFlags function. For the local server,
436436
// features are resolved once at startup from --features CLI flag and insiders mode.
437437
func createFeatureChecker(enabledFeatures []string, insidersMode bool) inventory.FeatureFlagChecker {
438-
featureSet := github.ResolveFeatureFlags(github.FeatureFlagsFromStrings(enabledFeatures), insidersMode)
438+
featureSet := github.ResolveFeatureFlags(enabledFeatures, insidersMode)
439439
return func(_ context.Context, flagName inventory.FeatureFlag) (bool, error) {
440-
return featureSet[flagName], nil
440+
return featureSet[string(flagName)], nil
441441
}
442442
}
443443

‎pkg/github/feature_flags.go‎

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,46 @@ import (
77
)
88

99
// MCPAppsFeatureFlag is the feature flag name for MCP Apps (interactive UI forms).
10-
const MCPAppsFeatureFlag inventory.FeatureFlag = "remote_mcp_ui_apps"
10+
const MCPAppsFeatureFlag = "remote_mcp_ui_apps"
1111

1212
// MCPAppsDisableFormDeferralFeatureFlag disables handing write-tool calls off
1313
// to MCP App forms while preserving MCP Apps UI metadata and result views.
14-
const MCPAppsDisableFormDeferralFeatureFlag inventory.FeatureFlag = "mcp_apps_disable_form_deferral"
14+
const MCPAppsDisableFormDeferralFeatureFlag = "mcp_apps_disable_form_deferral"
1515

1616
// FeatureFlagCSVOutput is the feature flag name for CSV output on list tools.
17-
const FeatureFlagCSVOutput inventory.FeatureFlag = "csv_output"
17+
const FeatureFlagCSVOutput = "csv_output"
1818

1919
// FeatureFlagIFCLabels is the feature flag name for IFC security labels in tool results.
20-
const FeatureFlagIFCLabels inventory.FeatureFlag = "ifc_labels"
20+
const FeatureFlagIFCLabels = "ifc_labels"
2121

2222
// FeatureFlagFileBlame is the feature flag name for the get_file_blame tool,
2323
// which exposes git blame information for a file. It is gated so the extra tool
2424
// is not advertised by default, keeping the tool surface small unless opted in.
25-
const FeatureFlagFileBlame inventory.FeatureFlag = "file_blame"
25+
const FeatureFlagFileBlame = "file_blame"
2626

2727
// FeatureFlagIssueDependencies is the feature flag name for the issue dependency
2828
// tools (issue_dependency_read / issue_dependency_write), which read and edit an
2929
// issue's blocked-by / blocking relationships. It is gated so these tools are not
3030
// advertised in the default surface, keeping the fixed tool-schema cost small
3131
// unless explicitly opted in.
32-
const FeatureFlagIssueDependencies inventory.FeatureFlag = "issue_dependencies"
32+
const FeatureFlagIssueDependencies = "issue_dependencies"
3333

3434
// FeatureFlagDuplicateDetection is the feature flag name for the find_duplicate
3535
// tool, which returns ranked duplicate candidates for an existing issue. It is
3636
// gated so the extra tool is not advertised by default, and is deliberately
3737
// excluded from insiders mode so duplicate detection is only ever an explicit
3838
// opt-in.
39-
const FeatureFlagDuplicateDetection inventory.FeatureFlag = "duplicate_detection"
39+
const FeatureFlagDuplicateDetection = "duplicate_detection"
4040

4141
// FeatureFlagThreadResolutionReason exposes resolution reasons for Copilot review threads.
42-
const FeatureFlagThreadResolutionReason inventory.FeatureFlag = "thread_resolution_reason"
42+
const FeatureFlagThreadResolutionReason = "thread_resolution_reason"
4343

4444
// AllowedFeatureFlags is the allowlist of feature flags that can be enabled
4545
// by users via --features CLI flag, X-MCP-Features HTTP header, or the
4646
// features URL query parameter.
4747
// Only flags in this list are accepted; unknown flags are silently ignored.
4848
// This is the single source of truth for which flags are user-controllable.
49-
var AllowedFeatureFlags = []inventory.FeatureFlag{
49+
var AllowedFeatureFlags = []string{
5050
MCPAppsFeatureFlag,
5151
MCPAppsDisableFormDeferralFeatureFlag,
5252
FeatureFlagCSVOutput,
@@ -63,7 +63,7 @@ var AllowedFeatureFlags = []inventory.FeatureFlag{
6363
// When insiders mode is active, all flags in this list are treated as enabled.
6464
// This is the single source of truth for what "insiders" means in terms of
6565
// feature flag expansion.
66-
var InsidersFeatureFlags = []inventory.FeatureFlag{
66+
var InsidersFeatureFlags = []string{
6767
MCPAppsFeatureFlag,
6868
FeatureFlagCSVOutput,
6969
FeatureFlagFileBlame,
@@ -75,20 +75,22 @@ type FeatureFlags struct {
7575
LockdownMode bool
7676
}
7777

78-
func featureEnabledRule(feature inventory.FeatureFlag) inventory.FeatureRule {
78+
func featureEnabledRule(feature string) inventory.FeatureRule {
79+
flag := inventory.FeatureFlag(feature)
7980
return inventory.NewFeatureRule(
80-
[]inventory.FeatureFlag{feature},
81+
[]inventory.FeatureFlag{flag},
8182
func(featureAsBool inventory.FeatureResolver) bool {
82-
return featureAsBool(feature)
83+
return featureAsBool(flag)
8384
},
8485
)
8586
}
8687

87-
func featureDisabledRule(feature inventory.FeatureFlag) inventory.FeatureRule {
88+
func featureDisabledRule(feature string) inventory.FeatureRule {
89+
flag := inventory.FeatureFlag(feature)
8890
return inventory.NewFeatureRule(
89-
[]inventory.FeatureFlag{feature},
91+
[]inventory.FeatureFlag{flag},
9092
func(featureAsBool inventory.FeatureResolver) bool {
91-
return !featureAsBool(feature)
93+
return !featureAsBool(flag)
9294
},
9395
)
9496
}
@@ -100,15 +102,6 @@ var (
100102
pullRequestsConsolidatedRule = featureDisabledRule(FeatureFlagPullRequestsGranular)
101103
)
102104

103-
// FeatureFlagsFromStrings converts feature names from transport or CLI input.
104-
func FeatureFlagsFromStrings(features []string) []inventory.FeatureFlag {
105-
result := make([]inventory.FeatureFlag, len(features))
106-
for i, feature := range features {
107-
result[i] = inventory.FeatureFlag(feature)
108-
}
109-
return result
110-
}
111-
112105
// ResolveFeatureFlags computes the effective set of enabled feature flags by:
113106
// 1. Taking the user-supplied flags (from --features or HTTP request
114107
// configuration) and
@@ -125,8 +118,8 @@ func FeatureFlagsFromStrings(features []string) []inventory.FeatureFlag {
125118
// only through insiders mode and cannot be enabled by user input.
126119
//
127120
// Returns a set (map) for O(1) lookup by the feature checker.
128-
func ResolveFeatureFlags(enabledFeatures []inventory.FeatureFlag, insidersMode bool) map[inventory.FeatureFlag]bool {
129-
effective := make(map[inventory.FeatureFlag]bool)
121+
func ResolveFeatureFlags(enabledFeatures []string, insidersMode bool) map[string]bool {
122+
effective := make(map[string]bool)
130123
for _, feature := range enabledFeatures {
131124
if slices.Contains(AllowedFeatureFlags, feature) {
132125
effective[feature] = true

‎pkg/github/feature_flags_test.go‎

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -140,26 +140,26 @@ func TestResolveFeatureFlags(t *testing.T) {
140140

141141
tests := []struct {
142142
name string
143-
enabledFeatures []inventory.FeatureFlag
143+
enabledFeatures []string
144144
insidersMode bool
145-
expectedFlags []inventory.FeatureFlag
146-
unexpectedFlags []inventory.FeatureFlag
145+
expectedFlags []string
146+
unexpectedFlags []string
147147
}{
148148
{
149149
name: "no features, no insiders",
150150
enabledFeatures: nil,
151151
expectedFlags: nil,
152-
unexpectedFlags: []inventory.FeatureFlag{MCPAppsFeatureFlag},
152+
unexpectedFlags: []string{MCPAppsFeatureFlag},
153153
},
154154
{
155155
name: "explicit feature enabled",
156-
enabledFeatures: []inventory.FeatureFlag{MCPAppsFeatureFlag},
157-
expectedFlags: []inventory.FeatureFlag{MCPAppsFeatureFlag},
156+
enabledFeatures: []string{MCPAppsFeatureFlag},
157+
expectedFlags: []string{MCPAppsFeatureFlag},
158158
},
159159
{
160160
name: "MCP Apps form deferral can be disabled directly",
161-
enabledFeatures: []inventory.FeatureFlag{MCPAppsDisableFormDeferralFeatureFlag},
162-
expectedFlags: []inventory.FeatureFlag{MCPAppsDisableFormDeferralFeatureFlag},
161+
enabledFeatures: []string{MCPAppsDisableFormDeferralFeatureFlag},
162+
expectedFlags: []string{MCPAppsDisableFormDeferralFeatureFlag},
163163
},
164164
{
165165
name: "insiders mode enables insiders flags",
@@ -171,50 +171,50 @@ func TestResolveFeatureFlags(t *testing.T) {
171171
name: "insiders mode does not auto-enable ifc labels",
172172
enabledFeatures: nil,
173173
insidersMode: true,
174-
unexpectedFlags: []inventory.FeatureFlag{FeatureFlagIFCLabels},
174+
unexpectedFlags: []string{FeatureFlagIFCLabels},
175175
},
176176
{
177177
name: "insiders mode does not disable MCP Apps form deferral",
178178
enabledFeatures: nil,
179179
insidersMode: true,
180-
unexpectedFlags: []inventory.FeatureFlag{MCPAppsDisableFormDeferralFeatureFlag},
180+
unexpectedFlags: []string{MCPAppsDisableFormDeferralFeatureFlag},
181181
},
182182
{
183183
name: "ifc_labels can be directly enabled",
184-
enabledFeatures: []inventory.FeatureFlag{FeatureFlagIFCLabels},
185-
expectedFlags: []inventory.FeatureFlag{FeatureFlagIFCLabels},
184+
enabledFeatures: []string{FeatureFlagIFCLabels},
185+
expectedFlags: []string{FeatureFlagIFCLabels},
186186
},
187187
{
188188
name: "unknown flags are filtered out",
189-
enabledFeatures: []inventory.FeatureFlag{"unknown_flag", "another_unknown"},
190-
unexpectedFlags: []inventory.FeatureFlag{"unknown_flag", "another_unknown"},
189+
enabledFeatures: []string{"unknown_flag", "another_unknown"},
190+
unexpectedFlags: []string{"unknown_flag", "another_unknown"},
191191
},
192192
{
193193
name: "mix of known and unknown flags",
194-
enabledFeatures: []inventory.FeatureFlag{MCPAppsFeatureFlag, "unknown_flag"},
195-
expectedFlags: []inventory.FeatureFlag{MCPAppsFeatureFlag},
196-
unexpectedFlags: []inventory.FeatureFlag{"unknown_flag"},
194+
enabledFeatures: []string{MCPAppsFeatureFlag, "unknown_flag"},
195+
expectedFlags: []string{MCPAppsFeatureFlag},
196+
unexpectedFlags: []string{"unknown_flag"},
197197
},
198198
{
199199
name: "user-only flags can be enabled but are not turned on by insiders",
200-
enabledFeatures: []inventory.FeatureFlag{FeatureFlagIssuesGranular},
200+
enabledFeatures: []string{FeatureFlagIssuesGranular},
201201
insidersMode: false,
202-
expectedFlags: []inventory.FeatureFlag{FeatureFlagIssuesGranular},
202+
expectedFlags: []string{FeatureFlagIssuesGranular},
203203
},
204204
{
205205
name: "thread resolution reason can be directly enabled",
206-
enabledFeatures: []inventory.FeatureFlag{FeatureFlagThreadResolutionReason},
207-
expectedFlags: []inventory.FeatureFlag{FeatureFlagThreadResolutionReason},
206+
enabledFeatures: []string{FeatureFlagThreadResolutionReason},
207+
expectedFlags: []string{FeatureFlagThreadResolutionReason},
208208
},
209209
{
210210
name: "insiders does not enable user-only allowed flags",
211211
enabledFeatures: nil,
212212
insidersMode: true,
213-
unexpectedFlags: []inventory.FeatureFlag{FeatureFlagIssuesGranular, FeatureFlagPullRequestsGranular},
213+
unexpectedFlags: []string{FeatureFlagIssuesGranular, FeatureFlagPullRequestsGranular},
214214
},
215215
{
216216
name: "explicit plus insiders deduplicates",
217-
enabledFeatures: []inventory.FeatureFlag{MCPAppsFeatureFlag},
217+
enabledFeatures: []string{MCPAppsFeatureFlag},
218218
insidersMode: true,
219219
expectedFlags: InsidersFeatureFlags,
220220
},
@@ -254,12 +254,12 @@ func TestThreadResolutionReasonToolVariants(t *testing.T) {
254254
},
255255
{
256256
name: "granular flag off",
257-
flags: []inventory.FeatureFlag{FeatureFlagPullRequestsGranular},
257+
flags: []inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagPullRequestsGranular)},
258258
toolName: "resolve_review_thread",
259259
},
260260
{
261261
name: "granular flag on",
262-
flags: []inventory.FeatureFlag{FeatureFlagPullRequestsGranular, FeatureFlagThreadResolutionReason},
262+
flags: []inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagPullRequestsGranular), FeatureFlagThreadResolutionReason},
263263
toolName: "resolve_review_thread",
264264
hasReason: true,
265265
},
@@ -271,7 +271,7 @@ func TestThreadResolutionReasonToolVariants(t *testing.T) {
271271
},
272272
{
273273
name: "granular flag on GHES",
274-
flags: []inventory.FeatureFlag{FeatureFlagPullRequestsGranular, FeatureFlagThreadResolutionReason},
274+
flags: []inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagPullRequestsGranular), FeatureFlagThreadResolutionReason},
275275
host: utils.HostTypeGHES,
276276
toolName: "resolve_review_thread",
277277
},

‎pkg/github/granular_tools_test.go‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@ import (
2020
"github.com/stretchr/testify/require"
2121
)
2222

23-
func granularToolsForToolset(toolsetID inventory.ToolsetID, featureFlag inventory.FeatureFlag) []inventory.ServerTool {
23+
func granularToolsForToolset(toolsetID inventory.ToolsetID, featureFlag string) []inventory.ServerTool {
24+
flag := inventory.FeatureFlag(featureFlag)
2425
var result []inventory.ServerTool
2526
for _, tool := range AllTools(translations.NullTranslationHelper) {
2627
features := tool.FeatureRule.Features()
2728
usesFeature := false
2829
for _, feature := range features {
29-
usesFeature = usesFeature || feature == featureFlag
30+
usesFeature = usesFeature || feature == flag
3031
}
3132
if tool.Toolset.ID == toolsetID && usesFeature &&
32-
tool.FeatureRule.Enabled(func(flag inventory.FeatureFlag) bool { return flag == featureFlag }) {
33+
tool.FeatureRule.Enabled(func(feature inventory.FeatureFlag) bool { return feature == flag }) {
3334
result = append(result, tool)
3435
}
3536
}
@@ -108,7 +109,7 @@ func TestIssuesGranularToolset(t *testing.T) {
108109

109110
t.Run("all granular tools have correct feature flag", func(t *testing.T) {
110111
for _, tool := range granularToolsForToolset(ToolsetMetadataIssues.ID, FeatureFlagIssuesGranular) {
111-
assert.Equal(t, []inventory.FeatureFlag{FeatureFlagIssuesGranular}, tool.FeatureRule.Features(), "tool %s", tool.Tool.Name)
112+
assert.Equal(t, []inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagIssuesGranular)}, tool.FeatureRule.Features(), "tool %s", tool.Tool.Name)
112113
}
113114
})
114115
}
@@ -144,7 +145,7 @@ func TestPullRequestsGranularToolset(t *testing.T) {
144145

145146
t.Run("all granular tools have correct feature flag", func(t *testing.T) {
146147
for _, tool := range granularToolsForToolset(ToolsetMetadataPullRequests.ID, FeatureFlagPullRequestsGranular) {
147-
assert.Contains(t, tool.FeatureRule.Features(), FeatureFlagPullRequestsGranular, "tool %s", tool.Tool.Name)
148+
assert.Contains(t, tool.FeatureRule.Features(), inventory.FeatureFlag(FeatureFlagPullRequestsGranular), "tool %s", tool.Tool.Name)
148149
}
149150
})
150151
}

‎pkg/github/issues_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1833,7 +1833,7 @@ func Test_CreateIssue(t *testing.T) {
18331833
serverTool := IssueWrite(translations.NullTranslationHelper)
18341834
tool := serverTool.Tool
18351835
require.NoError(t, toolsnaps.Test(tool.Name, tool))
1836-
require.Equal(t, []inventory.FeatureFlag{FeatureFlagIssuesGranular}, serverTool.FeatureRule.Features())
1836+
require.Equal(t, []inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagIssuesGranular)}, serverTool.FeatureRule.Features())
18371837

18381838
assert.Equal(t, "issue_write", tool.Name)
18391839
assert.NotEmpty(t, tool.Description)

‎pkg/github/pullrequests.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,21 +1908,21 @@ Available methods:
19081908
})
19091909
if withResolutionReason {
19101910
st.FeatureRule = inventory.NewFeatureRule(
1911-
[]inventory.FeatureFlag{FeatureFlagThreadResolutionReason, FeatureFlagPullRequestsGranular},
1911+
[]inventory.FeatureFlag{FeatureFlagThreadResolutionReason, inventory.FeatureFlag(FeatureFlagPullRequestsGranular)},
19121912
func(featureAsBool inventory.FeatureResolver) bool {
19131913
return featureAsBool(FeatureFlagThreadResolutionReason) &&
1914-
!featureAsBool(FeatureFlagPullRequestsGranular)
1914+
!featureAsBool(inventory.FeatureFlag(FeatureFlagPullRequestsGranular))
19151915
},
19161916
)
19171917
} else {
19181918
if cfg.hostType == utils.HostTypeGHES {
19191919
st.FeatureRule = pullRequestsConsolidatedRule
19201920
} else {
19211921
st.FeatureRule = inventory.NewFeatureRule(
1922-
[]inventory.FeatureFlag{FeatureFlagThreadResolutionReason, FeatureFlagPullRequestsGranular},
1922+
[]inventory.FeatureFlag{FeatureFlagThreadResolutionReason, inventory.FeatureFlag(FeatureFlagPullRequestsGranular)},
19231923
func(featureAsBool inventory.FeatureResolver) bool {
19241924
return !featureAsBool(FeatureFlagThreadResolutionReason) &&
1925-
!featureAsBool(FeatureFlagPullRequestsGranular)
1925+
!featureAsBool(inventory.FeatureFlag(FeatureFlagPullRequestsGranular))
19261926
},
19271927
)
19281928
}

‎pkg/github/pullrequests_granular.go‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -751,19 +751,19 @@ func granularResolveReviewThread(t translations.TranslationHelperFunc, withResol
751751
switch {
752752
case withResolutionReason:
753753
st.FeatureRule = inventory.NewFeatureRule(
754-
[]inventory.FeatureFlag{FeatureFlagPullRequestsGranular, FeatureFlagThreadResolutionReason},
754+
[]inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagPullRequestsGranular), FeatureFlagThreadResolutionReason},
755755
func(featureAsBool inventory.FeatureResolver) bool {
756-
return featureAsBool(FeatureFlagPullRequestsGranular) &&
756+
return featureAsBool(inventory.FeatureFlag(FeatureFlagPullRequestsGranular)) &&
757757
featureAsBool(FeatureFlagThreadResolutionReason)
758758
},
759759
)
760760
case cfg.hostType == utils.HostTypeGHES:
761761
st.FeatureRule = pullRequestsGranularFeatureRule
762762
default:
763763
st.FeatureRule = inventory.NewFeatureRule(
764-
[]inventory.FeatureFlag{FeatureFlagPullRequestsGranular, FeatureFlagThreadResolutionReason},
764+
[]inventory.FeatureFlag{inventory.FeatureFlag(FeatureFlagPullRequestsGranular), FeatureFlagThreadResolutionReason},
765765
func(featureAsBool inventory.FeatureResolver) bool {
766-
return featureAsBool(FeatureFlagPullRequestsGranular) &&
766+
return featureAsBool(inventory.FeatureFlag(FeatureFlagPullRequestsGranular)) &&
767767
!featureAsBool(FeatureFlagThreadResolutionReason)
768768
},
769769
)

0 commit comments

Comments
 (0)