⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
src/signals/focus-manifest.ts builds two parallel public-facing outputs from the same maintainer
preferredLabels config when a PR doesn't carry one of them: a findings[] entry (with a detail
string) and a publicNextSteps[] entry. Both are meant to describe the same maintainer-configured label
list, filtered for public-safety before being interpolated into text shown to a contributor:
if (manifest.preferredLabels.length > 0 && preferredLabelHits.length === 0) {
// Public-safety filter before interpolation (#5945) -- mirrors safeExpectations below. ...
const safePreferredLabels = manifest.preferredLabels.filter(isFocusManifestPublicSafe).slice(0, 5);
const preferredLabelsDetail =
safePreferredLabels.length > 0
? `Maintainer prefers labels: ${safePreferredLabels.join(", ")}.`
: "No maintainer-preferred label applied.";
findings.push({
code: "manifest_missing_preferred_label",
severity: "info",
title: "No maintainer-preferred label applied",
detail: preferredLabelsDetail,
action: "Consider applying a maintainer-preferred label so triage stays aligned.",
});
publicNextSteps.push(`Consider a maintainer-preferred label (${manifest.preferredLabels.slice(0, 3).join(", ")}).`);
}
The findings[].detail string is correctly built from safePreferredLabels — the list already filtered
through isFocusManifestPublicSafe, per the leading comment's own stated intent ("Public-safety filter
before interpolation"). The publicNextSteps line two lines below, however, is built from the RAW,
unfiltered manifest.preferredLabels.slice(0, 3) instead of the already-computed safePreferredLabels.
Both findings and publicNextSteps do get a later, blanket .filter(isFocusManifestPublicSafe) pass
elsewhere in the function (around line 867) — but that later filter operates on each finished sentence
as a whole string, not per-label. So if just one of the maintainer's first three configured
preferredLabels contains a term isFocusManifestPublicSafe rejects, the ENTIRE
"Consider a maintainer-preferred label (...)" sentence is dropped from publicNextSteps outright —
even though the sibling findings[].detail sentence, built from the pre-filtered safePreferredLabels,
would still correctly show the other 1-2 safe labels. The two outputs describing the identical
"no preferred label applied" event silently disagree on how much information survives the safety
filter, for no stated reason.
Requirements
- The
publicNextSteps.push(...) line for the manifest_missing_preferred_label case must use the
already-computed safePreferredLabels (filtered through isFocusManifestPublicSafe) instead of the
raw manifest.preferredLabels, so both output surfaces for this one event are built from the same
safety-filtered label list.
- Must not compute a second, independent filtered list — reuse the
safePreferredLabels binding already
in scope a few lines above, so the two outputs can never re-diverge.
- Must not change the
findings[].detail behavior, the later blanket isFocusManifestPublicSafe pass on
the finished sentences, or any other finding/next-step in this function.
Deliverables
Both Deliverables are required in the same PR.
Test Coverage Requirements
This repo's Codecov patch gate requires 99%+ patch coverage on every changed line and branch under
src/**. src/signals/focus-manifest.ts is inside src/**. The new test must exercise the actual
mixed safe/unsafe-label scenario end-to-end through the function that builds findings/publicNextSteps
(not just unit-test isFocusManifestPublicSafe in isolation) so the fix is verified against real output.
Expected Outcome
When a maintainer's configured preferredLabels list mixes public-safe and non-public-safe entries, the
publicNextSteps "Consider a maintainer-preferred label" suggestion shows exactly the same safe subset
of labels the sibling findings[].detail sentence already shows, instead of being silently dropped
entirely whenever any one of the first three configured labels happens to be unsafe.
Links & Resources
src/signals/focus-manifest.ts — the manifest_missing_preferred_label block (around lines 802-819).
Context
src/signals/focus-manifest.tsbuilds two parallel public-facing outputs from the same maintainerpreferredLabelsconfig when a PR doesn't carry one of them: afindings[]entry (with adetailstring) and a
publicNextSteps[]entry. Both are meant to describe the same maintainer-configured labellist, filtered for public-safety before being interpolated into text shown to a contributor:
The
findings[].detailstring is correctly built fromsafePreferredLabels— the list already filteredthrough
isFocusManifestPublicSafe, per the leading comment's own stated intent ("Public-safety filterbefore interpolation"). The
publicNextStepsline two lines below, however, is built from the RAW,unfiltered
manifest.preferredLabels.slice(0, 3)instead of the already-computedsafePreferredLabels.Both
findingsandpublicNextStepsdo get a later, blanket.filter(isFocusManifestPublicSafe)passelsewhere in the function (around line 867) — but that later filter operates on each finished sentence
as a whole string, not per-label. So if just one of the maintainer's first three configured
preferredLabelscontains a termisFocusManifestPublicSaferejects, the ENTIRE"Consider a maintainer-preferred label (...)"sentence is dropped frompublicNextStepsoutright —even though the sibling
findings[].detailsentence, built from the pre-filteredsafePreferredLabels,would still correctly show the other 1-2 safe labels. The two outputs describing the identical
"no preferred label applied" event silently disagree on how much information survives the safety
filter, for no stated reason.
Requirements
publicNextSteps.push(...)line for themanifest_missing_preferred_labelcase must use thealready-computed
safePreferredLabels(filtered throughisFocusManifestPublicSafe) instead of theraw
manifest.preferredLabels, so both output surfaces for this one event are built from the samesafety-filtered label list.
safePreferredLabelsbinding alreadyin scope a few lines above, so the two outputs can never re-diverge.
findings[].detailbehavior, the later blanketisFocusManifestPublicSafepass onthe finished sentences, or any other finding/next-step in this function.
Deliverables
publicNextSteps's"Consider a maintainer-preferred label (...)"line is built fromsafePreferredLabels.slice(0, 3)instead ofmanifest.preferredLabels.slice(0, 3), verified by anew test where
manifest.preferredLabelscontains at least one label thatisFocusManifestPublicSaferejects among its first three entries and at least one that it accepts:assert that
publicNextStepsstill contains a "Consider a maintainer-preferred label" entrylisting only the accepted label(s), matching exactly what
findings[0].detaillists for the samecase (not silently dropped, and not listing the rejected label).
preferredLabelsare public-safe is unchanged —publicNextStepsstill lists the same labels(now via
safePreferredLabels, which is byte-identical to the raw list when nothing is filteredout) as it did before this fix.
Both Deliverables are required in the same PR.
Test Coverage Requirements
This repo's Codecov patch gate requires 99%+ patch coverage on every changed line and branch under
src/**.src/signals/focus-manifest.tsis insidesrc/**. The new test must exercise the actualmixed safe/unsafe-label scenario end-to-end through the function that builds
findings/publicNextSteps(not just unit-test
isFocusManifestPublicSafein isolation) so the fix is verified against real output.Expected Outcome
When a maintainer's configured
preferredLabelslist mixes public-safe and non-public-safe entries, thepublicNextSteps"Consider a maintainer-preferred label" suggestion shows exactly the same safe subsetof labels the sibling
findings[].detailsentence already shows, instead of being silently droppedentirely whenever any one of the first three configured labels happens to be unsafe.
Links & Resources
src/signals/focus-manifest.ts— themanifest_missing_preferred_labelblock (around lines 802-819).