diff --git a/src/signals/focus-manifest.ts b/src/signals/focus-manifest.ts index 2b4e4f4d50..69b088fc84 100644 --- a/src/signals/focus-manifest.ts +++ b/src/signals/focus-manifest.ts @@ -806,136 +806,3 @@ function summarize(manifest: FocusManifest, wanted: string[]): string { if (manifest.wantedPaths.length > 0) return "Maintainer focus manifest: change is outside the wanted areas."; return "Maintainer focus manifest applied with no path-specific verdict."; } - -export type ContributionLanePreference = "preferred" | "neutral" | "discouraged"; - -export type ContributionLanes = { - present: boolean; - source: FocusManifestSource; - directPrLane: ContributionLanePreference; - issueDiscoveryLane: ContributionLanePreference; - preferredEntryPaths: string[]; - discouragedEntryPaths: string[]; - validationExpectations: string[]; - issueEntryGuidance: string[]; - prEntryGuidance: string[]; - guidanceText: string[]; - warnings: string[]; - summary: string; -}; - -/** - * Derive public-safe {@link ContributionLanes} from a focus manifest. Output is - * deterministic: identical manifests produce identical lanes. No private scoring, - * reward context, or trust data is included. - */ -export function deriveContributionLanes(manifest: FocusManifest): ContributionLanes { - if (!manifest.present) { - return { - present: false, - source: manifest.source, - directPrLane: "neutral", - issueDiscoveryLane: "neutral", - preferredEntryPaths: [], - discouragedEntryPaths: [], - validationExpectations: [], - issueEntryGuidance: [], - prEntryGuidance: [], - guidanceText: [], - warnings: manifest.warnings, - summary: "No maintainer focus manifest; contribution lanes are not constrained (using neutral lane defaults).", - }; - } - - const safeWanted = manifest.wantedPaths.filter(isFocusManifestPublicSafe); - const safePublicNotes = manifest.publicNotes.filter(isFocusManifestPublicSafe); - - const validationExpectations: string[] = []; - if (manifest.linkedIssuePolicy === "required") validationExpectations.push("Link a tracked issue before opening a PR."); - else if (manifest.linkedIssuePolicy === "preferred") validationExpectations.push("Link a tracked issue if one exists."); - for (const e of manifest.testExpectations) { - if (isFocusManifestPublicSafe(e)) validationExpectations.push(e); - } - - const directPrLane: ContributionLanePreference = - manifest.issueDiscoveryPolicy === "encouraged" ? "discouraged" - : safeWanted.length > 0 ? "preferred" - : "neutral"; - - const issueDiscoveryLane: ContributionLanePreference = - manifest.issueDiscoveryPolicy === "encouraged" ? "preferred" - : manifest.issueDiscoveryPolicy === "discouraged" ? "discouraged" - : "neutral"; - - const issueEntryGuidance: string[] = []; - if (manifest.issueDiscoveryPolicy === "encouraged") { - issueEntryGuidance.push("Issue discovery reports are welcomed; search for gaps before opening a PR."); - } else if (manifest.issueDiscoveryPolicy === "discouraged") { - issueEntryGuidance.push("Prefer direct fixes over new issue reports; this repo discourages issue-discovery submissions."); - } - if (manifest.linkedIssuePolicy === "required") { - issueEntryGuidance.push("Issues must be linked to a PR before it is opened."); - } else if (manifest.linkedIssuePolicy === "preferred") { - issueEntryGuidance.push("Link an existing issue to your PR when one is available."); - } - - const prEntryGuidance: string[] = []; - if (safeWanted.length > 0) { - prEntryGuidance.push(`Focus changes on maintainer-wanted areas: ${safeWanted.slice(0, 5).join(", ")}.`); - } - if (manifest.preferredLabels.length > 0) { - const safeLabels = manifest.preferredLabels.filter(isFocusManifestPublicSafe); - if (safeLabels.length > 0) { - prEntryGuidance.push(`Apply a maintainer-preferred label to your PR: ${safeLabels.slice(0, 3).join(", ")}.`); - } - } - prEntryGuidance.push(...safePublicNotes); - const safeprEntryGuidance = [...new Set(prEntryGuidance)].filter(isFocusManifestPublicSafe); - - const guidanceText: string[] = []; - if (manifest.linkedIssuePolicy === "required") { - guidanceText.push("Link a tracked issue before opening a pull request."); - } else if (manifest.linkedIssuePolicy === "preferred") { - guidanceText.push("Linking a tracked issue is preferred before opening a pull request."); - } - if (manifest.preferredLabels.length > 0) { - const safeLabels = manifest.preferredLabels.filter(isFocusManifestPublicSafe); - if (safeLabels.length > 0) { - guidanceText.push(`Apply a maintainer-preferred label: ${safeLabels.slice(0, 3).join(", ")}.`); - } - } - guidanceText.push(...safePublicNotes); - - const warnings: string[] = []; - if (safeWanted.length === 0 && manifest.preferredLabels.length === 0) { - warnings.push("Contribution scope is unclear; focus manifest lacks wanted paths and preferred labels."); - } - if (manifest.testExpectations.filter(isFocusManifestPublicSafe).length === 0) { - warnings.push("Validation expectations are not defined in the focus manifest."); - } - - const summary = buildLanesSummary(manifest, directPrLane, issueDiscoveryLane); - - return { - present: true, - source: manifest.source, - directPrLane, - issueDiscoveryLane, - preferredEntryPaths: safeWanted, - discouragedEntryPaths: [], - validationExpectations, - issueEntryGuidance: issueEntryGuidance.filter(isFocusManifestPublicSafe), - prEntryGuidance: safeprEntryGuidance, - guidanceText: guidanceText.filter(isFocusManifestPublicSafe), - warnings, - summary, - }; -} - -function buildLanesSummary(manifest: FocusManifest, directPrLane: ContributionLanePreference, issueDiscoveryLane: ContributionLanePreference): string { - if (issueDiscoveryLane === "preferred" && directPrLane === "discouraged") return "Issue-discovery is the preferred contribution mode for this repo."; - if (issueDiscoveryLane === "discouraged" && manifest.wantedPaths.length > 0) return "Direct PRs focused on the wanted areas are the preferred contribution mode."; - if (directPrLane === "preferred") return "Direct PRs on the maintainer-wanted areas are preferred."; - if (issueDiscoveryLane === "discouraged") return "Direct PRs are preferred; issue-discovery submissions are discouraged."; - return "Contribution lanes are guided by the maintainer focus manifest."; -} diff --git a/test/unit/focus-manifest.test.ts b/test/unit/focus-manifest.test.ts index 310d59fcbf..7a03389de7 100644 --- a/test/unit/focus-manifest.test.ts +++ b/test/unit/focus-manifest.test.ts @@ -5,7 +5,6 @@ import { buildFocusManifestGuidance, compileFocusManifestPolicy, contentLaneConfigToJson, - deriveContributionLanes, experimentalConfigToJson, featuresConfigToJson, gateConfigToJson, @@ -965,161 +964,6 @@ describe("compileFocusManifestPolicy", () => { }); }); -describe("deriveContributionLanes", () => { - it("returns neutral lanes with no constraints when no manifest is present", () => { - const lanes = deriveContributionLanes(parseFocusManifest(null)); - expect(lanes.present).toBe(false); - expect(lanes.directPrLane).toBe("neutral"); - expect(lanes.issueDiscoveryLane).toBe("neutral"); - expect(lanes.preferredEntryPaths).toEqual([]); - expect(lanes.discouragedEntryPaths).toEqual([]); - expect(lanes.validationExpectations).toEqual([]); - expect(lanes.issueEntryGuidance).toEqual([]); - expect(lanes.prEntryGuidance).toEqual([]); - expect(lanes.summary).toMatch(/not constrained/i); - }); - - it("marks direct-PR as preferred when wanted paths are declared", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/", "lib/"] })); - expect(lanes.present).toBe(true); - expect(lanes.directPrLane).toBe("preferred"); - expect(lanes.issueDiscoveryLane).toBe("neutral"); - expect(lanes.preferredEntryPaths).toEqual(["src/", "lib/"]); - expect(lanes.prEntryGuidance.join(" ")).toMatch(/src\//); - expect(lanes.summary).toMatch(/wanted areas are preferred/i); - }); - - it("marks issue-discovery as preferred and direct-PR as discouraged when issueDiscoveryPolicy is encouraged", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ issueDiscoveryPolicy: "encouraged" })); - expect(lanes.directPrLane).toBe("discouraged"); - expect(lanes.issueDiscoveryLane).toBe("preferred"); - expect(lanes.issueEntryGuidance.join(" ")).toMatch(/welcomed|search for gaps/i); - expect(lanes.summary).toMatch(/issue.discovery is the preferred/i); - }); - - it("marks issue-discovery as discouraged when issueDiscoveryPolicy is discouraged", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"], issueDiscoveryPolicy: "discouraged" })); - expect(lanes.issueDiscoveryLane).toBe("discouraged"); - expect(lanes.directPrLane).toBe("preferred"); - expect(lanes.issueEntryGuidance.join(" ")).toMatch(/prefer direct fixes|discourages/i); - expect(lanes.summary).toMatch(/wanted areas are the preferred/i); - }); - - it("surfaces validation expectations from testExpectations and linkedIssuePolicy", () => { - const lanes = deriveContributionLanes( - parseFocusManifest({ wantedPaths: ["src/"], linkedIssuePolicy: "required", testExpectations: ["unit tests for new branches", "npm run test:ci"] }), - ); - expect(lanes.validationExpectations).toContain("Link a tracked issue before opening a PR."); - expect(lanes.validationExpectations).toContain("unit tests for new branches"); - expect(lanes.validationExpectations).toContain("npm run test:ci"); - }); - - it("produces preferred validation hint for linkedIssuePolicy:preferred", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"], linkedIssuePolicy: "preferred" })); - expect(lanes.validationExpectations).toContain("Link a tracked issue if one exists."); - expect(lanes.issueEntryGuidance).toContain("Link an existing issue to your PR when one is available."); - }); - - it("includes required link requirement in both validation expectations and issue entry guidance", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"], linkedIssuePolicy: "required" })); - expect(lanes.validationExpectations).toContain("Link a tracked issue before opening a PR."); - expect(lanes.issueEntryGuidance).toContain("Issues must be linked to a PR before it is opened."); - }); - - it("ignores legacy blocked paths in discouragedEntryPaths and PR entry guidance", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"], blockedPaths: ["migrations/", "infra/secrets.tf"] })); - expect(lanes.discouragedEntryPaths).toEqual([]); - expect(lanes.prEntryGuidance.join(" ")).not.toMatch(/migrations\/|infra\/secrets\.tf/); - }); - - it("includes preferred labels in PR entry guidance", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"], preferredLabels: ["bug", "good first issue"] })); - expect(lanes.prEntryGuidance.join(" ")).toMatch(/bug|good first issue/); - }); - - it("includes maintainer public notes in PR entry guidance", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"], publicNotes: ["Prefer small, focused PRs."] })); - expect(lanes.prEntryGuidance).toContain("Prefer small, focused PRs."); - }); - - it("excludes maintainerNotes from all output fields", () => { - const lanes = deriveContributionLanes( - parseFocusManifest({ wantedPaths: ["src/"], maintainerNotes: ["Internal: ping @owner before touching the queue processor."] }), - ); - const serialized = JSON.stringify(lanes); - expect(serialized).not.toMatch(/ping @owner/); - expect(serialized).not.toMatch(/Internal:/); - }); - - it("filters public notes containing forbidden language before including them in prEntryGuidance", () => { - const lanes = deriveContributionLanes( - parseFocusManifest({ wantedPaths: ["src/"], publicNotes: ["Maximize your reward payout", "Keep PRs focused."] }), - ); - expect(lanes.prEntryGuidance).not.toContain("Maximize your reward payout"); - expect(lanes.prEntryGuidance).toContain("Keep PRs focused."); - }); - - it("filters testExpectations containing forbidden language before including them in validationExpectations", () => { - const lanes = deriveContributionLanes( - parseFocusManifest({ wantedPaths: ["src/"], testExpectations: ["Submit your wallet seed phrase", "npm run test:ci"] }), - ); - expect(lanes.validationExpectations).not.toContain("Submit your wallet seed phrase"); - expect(lanes.validationExpectations).toContain("npm run test:ci"); - }); - - it("preserves source from the manifest", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ wantedPaths: ["src/"] }, "repo_file")); - expect(lanes.source).toBe("repo_file"); - }); - - it("passes a comprehensive manifest fixture end-to-end with all fields populated", () => { - const manifest = parseFocusManifest({ - source: "repo_file", - wantedPaths: ["src/", "packages/*/lib"], - blockedPaths: ["migrations/"], - preferredLabels: ["bug", "good first issue"], - linkedIssuePolicy: "required", - testExpectations: ["unit tests for new branches"], - issueDiscoveryPolicy: "discouraged", - maintainerNotes: ["Internal: ping @owner"], - publicNotes: ["Prefer small, focused PRs."], - }); - const lanes = deriveContributionLanes(manifest); - - expect(lanes.present).toBe(true); - expect(lanes.source).toBe("repo_file"); - expect(lanes.directPrLane).toBe("preferred"); - expect(lanes.issueDiscoveryLane).toBe("discouraged"); - expect(lanes.preferredEntryPaths).toContain("src/"); - expect(lanes.discouragedEntryPaths).toEqual([]); - expect(lanes.validationExpectations).toContain("Link a tracked issue before opening a PR."); - expect(lanes.validationExpectations).toContain("unit tests for new branches"); - expect(lanes.issueEntryGuidance.join(" ")).toMatch(/discourages/i); - expect(lanes.prEntryGuidance.join(" ")).toMatch(/bug|good first issue/i); - expect(lanes.prEntryGuidance).toContain("Prefer small, focused PRs."); - expect(lanes.summary).toMatch(/wanted areas/i); - - const serialized = JSON.stringify(lanes); - expect(serialized).not.toMatch(/ping @owner/); - expect(serialized).not.toMatch(/\b(wallet|hotkey|coldkey|raw trust|trust score|payout|reward|farming|private reviewability)\b/i); - }); - - it("keeps both lanes neutral with a default summary when a present manifest declares no wanted paths or policies", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ preferredLabels: ["bug"] })); - expect(lanes.present).toBe(true); - expect(lanes.directPrLane).toBe("neutral"); - expect(lanes.issueDiscoveryLane).toBe("neutral"); - expect(lanes.summary).toMatch(/guided by the maintainer focus manifest/i); - }); - - it("recommends direct PRs when issue-discovery is discouraged without any wanted paths", () => { - const lanes = deriveContributionLanes(parseFocusManifest({ issueDiscoveryPolicy: "discouraged", preferredLabels: ["bug"] })); - expect(lanes.directPrLane).toBe("neutral"); - expect(lanes.issueDiscoveryLane).toBe("discouraged"); - expect(lanes.summary).toMatch(/direct prs are preferred; issue-discovery submissions are discouraged/i); - }); -}); - describe("public-safe invariant", () => { it("rejects forbidden compensation/secret language", () => { expect(isFocusManifestPublicSafe("Keep PRs focused")).toBe(true); diff --git a/test/unit/policy-sanitizer.test.ts b/test/unit/policy-sanitizer.test.ts index 69537d8054..fd7a79ed2c 100644 --- a/test/unit/policy-sanitizer.test.ts +++ b/test/unit/policy-sanitizer.test.ts @@ -13,7 +13,6 @@ import { buildGittensorConfigRecommendation, buildRegistrationReadiness, type In import { buildRepoSettingsPreview, decidePublicSurface, type InstallationHealthSummary as PreviewInstallHealth } from "../../src/signals/settings-preview"; import { compileFocusManifestPolicy, - deriveContributionLanes, isFocusManifestPublicSafe, parseFocusManifest, } from "../../src/signals/focus-manifest"; @@ -221,120 +220,6 @@ describe("sanitizeRoleText private term redaction", () => { }); }); -// --------------------------------------------------------------------------- -// Contribution lane validation — role cards and onboarding states -// --------------------------------------------------------------------------- - -describe("contribution lane output — public-safe via deriveContributionLanes", () => { - it("produces a neutral result when no manifest is present", () => { - const lanes = deriveContributionLanes(parseFocusManifest(null)); - expect(lanes.directPrLane).toBe("neutral"); - expect(lanes.issueDiscoveryLane).toBe("neutral"); - expect(lanes.preferredEntryPaths).toEqual([]); - expect(lanes.discouragedEntryPaths).toEqual([]); - expect(lanes.summary).toMatch(/neutral lane defaults/i); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("prefers direct PR lane when wanted paths are set", () => { - const manifest = parseFocusManifest({ wantedPaths: ["src/"], testExpectations: ["npm run test:ci"] }); - const lanes = deriveContributionLanes(manifest); - expect(lanes.directPrLane).toBe("preferred"); - expect(lanes.preferredEntryPaths).toContain("src/"); - expect(lanes.validationExpectations).toContain("npm run test:ci"); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("discourages issue discovery when policy is discouraged", () => { - const manifest = parseFocusManifest({ wantedPaths: ["src/"], issueDiscoveryPolicy: "discouraged" }); - const lanes = deriveContributionLanes(manifest); - expect(lanes.issueDiscoveryLane).toBe("discouraged"); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("prefers issue discovery when policy is encouraged", () => { - const manifest = parseFocusManifest({ issueDiscoveryPolicy: "encouraged", wantedPaths: ["src/"] }); - const lanes = deriveContributionLanes(manifest); - expect(lanes.issueDiscoveryLane).toBe("preferred"); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("includes a linked-issue guidance hint when policy is required", () => { - const manifest = parseFocusManifest({ wantedPaths: ["src/"], linkedIssuePolicy: "required" }); - const lanes = deriveContributionLanes(manifest); - expect(lanes.guidanceText.join(" ")).toMatch(/link a tracked issue/i); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("silently drops unsafe public notes from lanes", () => { - const manifest = parseFocusManifest({ - wantedPaths: ["src/"], - publicNotes: ["Maximize your reward payout.", "Keep PRs focused."], - }); - const lanes = deriveContributionLanes(manifest); - expect(lanes.guidanceText).not.toContain("Maximize your reward payout."); - expect(lanes.guidanceText).toContain("Keep PRs focused."); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("still surfaces safe wanted paths in PR guidance when the manifest mixes in a public-unsafe path", () => { - // A single public-unsafe wantedPaths entry must not drop the whole "Focus changes on maintainer-wanted - // areas" line via the all-or-nothing public-safety filter: the interpolation is built from the filtered - // safe paths, so the safe path still surfaces and the unsafe one never appears. - const manifest = parseFocusManifest({ wantedPaths: ["src/", "reward-farming/"] }); - const lanes = deriveContributionLanes(manifest); - const focusLine = lanes.prEntryGuidance.find((entry) => entry.startsWith("Focus changes on maintainer-wanted areas:")); - expect(focusLine).toBeDefined(); - expect(focusLine).toContain("src/"); - expect(focusLine).not.toContain("reward-farming/"); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - }); - - it("emits a warning when contribution scope is unclear", () => { - const manifest = parseFocusManifest({ wantedPaths: [], preferredLabels: [], issueDiscoveryPolicy: "encouraged" }); - const lanes = deriveContributionLanes(manifest); - expect(lanes.warnings.join(" ")).toMatch(/scope is unclear/i); - }); - - it("never exposes forbidden language across 400 property-based iterations", () => { - const stringPool = [ - "src/", - "migrations/", - "Keep PRs focused", - "Maximize your reward payout", - "paste your hotkey here", - "trusted label pipeline", - "raw trust score context", - "npm run test:ci", - ]; - const linkedIssuePolicies = ["required", "preferred", "optional"] as const; - const issueDiscoveryPolicies = ["encouraged", "neutral", "discouraged"] as const; - - let seed = 0x1337cafe; - const next = () => { - seed = (Math.imul(seed, 1664525) + 1013904223) >>> 0; - return seed / 0x100000000; - }; - const pick = (items: readonly T[]): T => items[Math.floor(next() * items.length)] as T; - const sample = (max: number): string[] => - Array.from({ length: Math.floor(next() * (max + 1)) }, () => pick(stringPool)); - - for (let i = 0; i < 400; i++) { - const manifest = parseFocusManifest({ - wantedPaths: sample(4), - blockedPaths: sample(2), - preferredLabels: sample(3), - linkedIssuePolicy: pick(linkedIssuePolicies), - issueDiscoveryPolicy: pick(issueDiscoveryPolicies), - publicNotes: sample(3), - testExpectations: sample(2), - }); - const lanes = deriveContributionLanes(manifest); - expect(JSON.stringify(lanes)).not.toMatch(FORBIDDEN_POLICY_PATTERN); - } - }); -}); - // --------------------------------------------------------------------------- // Readiness warnings and guidance — compileFocusManifestPolicy // ---------------------------------------------------------------------------