Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 0 additions & 133 deletions src/signals/focus-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.";
}
156 changes: 0 additions & 156 deletions test/unit/focus-manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
buildFocusManifestGuidance,
compileFocusManifestPolicy,
contentLaneConfigToJson,
deriveContributionLanes,
experimentalConfigToJson,
featuresConfigToJson,
gateConfigToJson,
Expand Down Expand Up @@ -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);
Expand Down
Loading