feat: route forgejo intake by workstream

This commit is contained in:
artale 2026-06-28 16:41:17 +02:00
parent ecca80f584
commit 501640e52e
4 changed files with 10 additions and 4 deletions

View File

@ -77,7 +77,7 @@ const WORKER_ROLES: Array<{ name: string; prompt: string; domainLock: string; ti
{ {
name: "devops", name: "devops",
prompt: "You are the DevOps Engineer. Own CI/CD configs, deployment scripts, infrastructure code. Never modify application code.", prompt: "You are the DevOps Engineer. Own CI/CD configs, deployment scripts, infrastructure code. Never modify application code.",
domainLock: ".github/", domainLock: ".forgejo/",
tier: "haiku", tier: "haiku",
}, },
]; ];

View File

@ -29,8 +29,11 @@ describe("forgejo intake", () => {
it("routes labels without LLM classification", () => { it("routes labels without LLM classification", () => {
expect(routeForgejoLabels(["seo"])).toBe("seo"); expect(routeForgejoLabels(["seo"])).toBe("seo");
expect(routeForgejoLabels(["domain/sec"])).toBe("security"); expect(routeForgejoLabels(["domain/sec"])).toBe("security");
expect(routeForgejoLabels(["sales"])).toBe("sales-marketing");
expect(routeForgejoLabels(["client", "bug"])).toBe("client-report"); expect(routeForgejoLabels(["client", "bug"])).toBe("client-report");
expect(routeForgejoLabels(["feedbackpilot"])).toBe("user-feedback");
expect(routeForgejoLabels(["pipeline"])).toBe("data-pipeline"); expect(routeForgejoLabels(["pipeline"])).toBe("data-pipeline");
expect(routeForgejoLabels(["infra"])).toBe("devops");
expect(routeForgejoLabels(["unknown"])).toBe("triage"); expect(routeForgejoLabels(["unknown"])).toBe("triage");
}); });

View File

@ -4,7 +4,7 @@ import { findPromptInjection, type PromptInjectionFinding } from "../core/prompt
import { emitChannelEvent } from "./channel.js"; import { emitChannelEvent } from "./channel.js";
export type ForgejoIntakeKind = "issue" | "pull" | "wiki"; export type ForgejoIntakeKind = "issue" | "pull" | "wiki";
export type ForgejoRoute = "security" | "seo" | "client-report" | "data-pipeline" | "dev" | "wiki" | "triage" | "human-review"; export type ForgejoRoute = "security" | "seo" | "sales-marketing" | "client-report" | "user-feedback" | "data-pipeline" | "devops" | "dev" | "wiki" | "triage" | "human-review";
export interface ForgejoIntakeSource { export interface ForgejoIntakeSource {
type: `forgejo_${ForgejoIntakeKind}`; type: `forgejo_${ForgejoIntakeKind}`;
@ -66,10 +66,13 @@ type ForgejoApiItem = {
export function routeForgejoLabels(labels: string[]): ForgejoRoute { export function routeForgejoLabels(labels: string[]): ForgejoRoute {
const normalized = labels.map((label) => label.toLowerCase()); const normalized = labels.map((label) => label.toLowerCase());
if (hasAny(normalized, ["security", "sec"])) return "security"; if (hasAny(normalized, ["security", "sec", "sec-first"])) return "security";
if (hasAny(normalized, ["seo"])) return "seo"; if (hasAny(normalized, ["seo"])) return "seo";
if (hasAny(normalized, ["sales", "marketing", "sale-marketing", "sales-marketing"])) return "sales-marketing";
if (hasAny(normalized, ["client", "report", "client-report"])) return "client-report"; if (hasAny(normalized, ["client", "report", "client-report"])) return "client-report";
if (hasAny(normalized, ["user", "users", "feedback", "feedbackpilot", "user-feedback"])) return "user-feedback";
if (hasAny(normalized, ["data", "pipeline", "data-pipeline"])) return "data-pipeline"; if (hasAny(normalized, ["data", "pipeline", "data-pipeline"])) return "data-pipeline";
if (hasAny(normalized, ["devops", "ops", "infra", "ci", "cd"])) return "devops";
if (hasAny(normalized, ["dev", "bug", "feature"])) return "dev"; if (hasAny(normalized, ["dev", "bug", "feature"])) return "dev";
if (hasAny(normalized, ["wiki", "docs"])) return "wiki"; if (hasAny(normalized, ["wiki", "docs"])) return "wiki";
return "triage"; return "triage";

View File

@ -30,7 +30,7 @@ const AGENT_TEMPLATES: Record<string, { role: string; tools: string[]; domainLoc
reviewer: { role: "Review code for correctness, security, style, test coverage", tools: ["read", "grep", "glob"], domainLock: "read-only" }, reviewer: { role: "Review code for correctness, security, style, test coverage", tools: ["read", "grep", "glob"], domainLock: "read-only" },
tester: { role: "Write and run tests, verify edge cases", tools: ["read", "write", "edit", "bash"], domainLock: "tests/" }, tester: { role: "Write and run tests, verify edge cases", tools: ["read", "write", "edit", "bash"], domainLock: "tests/" },
documenter: { role: "Write documentation, README updates, inline comments", tools: ["read", "write"], domainLock: "docs/" }, documenter: { role: "Write documentation, README updates, inline comments", tools: ["read", "write"], domainLock: "docs/" },
devops: { role: "Manage CI/CD, deployment config, infrastructure", tools: ["read", "write", "bash"], domainLock: ".github/" }, devops: { role: "Manage CI/CD, deployment config, infrastructure", tools: ["read", "write", "bash"], domainLock: ".forgejo/" },
security: { role: "Audit for vulnerabilities, OWASP, dependency risks", tools: ["read", "grep"], domainLock: "read-only" }, security: { role: "Audit for vulnerabilities, OWASP, dependency risks", tools: ["read", "grep"], domainLock: "read-only" },
}; };