diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 72a522f4..83e5ff79 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -176,7 +176,6 @@ export type { CompanySkillProjectScanRequest, CompanySkillProjectScanSkipped, CompanySkillProjectScanConflict, - CompanySkillProjectScanPruned, CompanySkillProjectScanResult, CompanySkillCreateRequest, CompanySkillFileDetail, @@ -562,7 +561,6 @@ export { companySkillProjectScanRequestSchema, companySkillProjectScanSkippedSchema, companySkillProjectScanConflictSchema, - companySkillProjectScanPrunedSchema, companySkillProjectScanResultSchema, companySkillCreateSchema, companySkillFileDetailSchema, diff --git a/packages/shared/src/types/company-skill.ts b/packages/shared/src/types/company-skill.ts index 69edaa1f..12834083 100644 --- a/packages/shared/src/types/company-skill.ts +++ b/packages/shared/src/types/company-skill.ts @@ -93,7 +93,6 @@ export interface CompanySkillImportResult { export interface CompanySkillProjectScanRequest { projectIds?: string[]; workspaceIds?: string[]; - dryRun?: boolean; } export interface CompanySkillProjectScanSkipped { @@ -119,14 +118,6 @@ export interface CompanySkillProjectScanConflict { reason: string; } -export interface CompanySkillProjectScanPruned { - skillId: string; - slug: string; - key: string; - sourceLocator: string | null; - affectedAgents: string[]; -} - export interface CompanySkillProjectScanResult { scannedProjects: number; scannedWorkspaces: number; @@ -135,9 +126,7 @@ export interface CompanySkillProjectScanResult { updated: CompanySkill[]; skipped: CompanySkillProjectScanSkipped[]; conflicts: CompanySkillProjectScanConflict[]; - pruned: CompanySkillProjectScanPruned[]; warnings: string[]; - dryRun: boolean; } export interface CompanySkillCreateRequest { diff --git a/packages/shared/src/types/index.ts b/packages/shared/src/types/index.ts index d1c56aca..888740d3 100644 --- a/packages/shared/src/types/index.ts +++ b/packages/shared/src/types/index.ts @@ -28,7 +28,6 @@ export type { CompanySkillProjectScanRequest, CompanySkillProjectScanSkipped, CompanySkillProjectScanConflict, - CompanySkillProjectScanPruned, CompanySkillProjectScanResult, CompanySkillCreateRequest, CompanySkillFileDetail, diff --git a/packages/shared/src/validators/company-skill.ts b/packages/shared/src/validators/company-skill.ts index 8739ccf4..58b9165d 100644 --- a/packages/shared/src/validators/company-skill.ts +++ b/packages/shared/src/validators/company-skill.ts @@ -76,7 +76,6 @@ export const companySkillUpdateAuthSchema = z.object({ export const companySkillProjectScanRequestSchema = z.object({ projectIds: z.array(z.string().uuid()).optional(), workspaceIds: z.array(z.string().uuid()).optional(), - dryRun: z.boolean().optional(), }); export const companySkillProjectScanSkippedSchema = z.object({ @@ -102,14 +101,6 @@ export const companySkillProjectScanConflictSchema = z.object({ reason: z.string().min(1), }); -export const companySkillProjectScanPrunedSchema = z.object({ - skillId: z.string().uuid(), - slug: z.string().min(1), - key: z.string().min(1), - sourceLocator: z.string().nullable(), - affectedAgents: z.array(z.string()), -}); - export const companySkillProjectScanResultSchema = z.object({ scannedProjects: z.number().int().nonnegative(), scannedWorkspaces: z.number().int().nonnegative(), @@ -118,9 +109,7 @@ export const companySkillProjectScanResultSchema = z.object({ updated: z.array(companySkillSchema), skipped: z.array(companySkillProjectScanSkippedSchema), conflicts: z.array(companySkillProjectScanConflictSchema), - pruned: z.array(companySkillProjectScanPrunedSchema), warnings: z.array(z.string()), - dryRun: z.boolean(), }); export const companySkillCreateSchema = z.object({ diff --git a/packages/shared/src/validators/index.ts b/packages/shared/src/validators/index.ts index 7e72c9fb..d1bc3929 100644 --- a/packages/shared/src/validators/index.ts +++ b/packages/shared/src/validators/index.ts @@ -48,7 +48,6 @@ export { companySkillProjectScanRequestSchema, companySkillProjectScanSkippedSchema, companySkillProjectScanConflictSchema, - companySkillProjectScanPrunedSchema, companySkillProjectScanResultSchema, companySkillCreateSchema, companySkillFileDetailSchema, diff --git a/server/src/__tests__/company-skills-prune.test.ts b/server/src/__tests__/company-skills-prune.test.ts index 3ccc8612..a75ab072 100644 --- a/server/src/__tests__/company-skills-prune.test.ts +++ b/server/src/__tests__/company-skills-prune.test.ts @@ -282,46 +282,4 @@ describeEmbeddedPostgres("scanProjectWorkspaces prune path", () => { ]), ); }); - - it("reports pruned skills without deleting when dryRun is true", async () => { - stubGitHubSource(["keep-skill"]); - - const { companySkillService } = await import("../services/company-skills.js"); - const svc = companySkillService(db); - const result = await svc.scanProjectWorkspaces(companyId, { dryRun: true }); - - // The result should flag dryRun and list what would be pruned - expect(result.dryRun).toBe(true); - expect(result.pruned).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - slug: "prune-skill", - affectedAgents: expect.arrayContaining(["Builder"]), - }), - ]), - ); - - // No warnings emitted (nothing was actually deleted) - const pruneWarnings = result.warnings.filter((w) => w.includes("prune-skill")); - expect(pruneWarnings).toHaveLength(0); - - // Both skills should still exist in the database - const remaining = await db - .select() - .from(companySkills) - .where(eq(companySkills.companyId, companyId)); - const remainingSlugs = remaining.map((r) => r.slug); - expect(remainingSlugs).toContain("keep-skill"); - expect(remainingSlugs).toContain("prune-skill"); - - // Agent config should be unchanged - const [agentRow] = await db - .select() - .from(agents) - .where(eq(agents.id, agentId)); - const config = agentRow!.adapterConfig as Record; - const syncConfig = config.paperclipSkillSync as Record; - const desiredSkills = syncConfig.desiredSkills as string[]; - expect(desiredSkills).toContain("test-org/test-skills/prune-skill"); - }); }); diff --git a/server/src/__tests__/company-skills-routes.test.ts b/server/src/__tests__/company-skills-routes.test.ts index a7a8766e..32656226 100644 --- a/server/src/__tests__/company-skills-routes.test.ts +++ b/server/src/__tests__/company-skills-routes.test.ts @@ -78,9 +78,7 @@ describe("company skill mutation permissions", () => { updated: [], skipped: [], conflicts: [], - pruned: [], warnings: [], - dryRun: false, }); mockLogActivity.mockResolvedValue(undefined); mockAccessService.canUser.mockResolvedValue(true); @@ -295,13 +293,9 @@ describe("company skill mutation permissions", () => { updated: [], skipped: [], conflicts: [], - pruned: [ - { skillId: "skill-1", slug: "ghost-skill", key: "vercel-labs/agent-browser/ghost-skill", sourceLocator: "https://github.com/vercel-labs/agent-browser", affectedAgents: ["Builder"] }, - ], warnings: [ 'Skill "ghost-skill" was removed from https://github.com/vercel-labs/agent-browser and detached from Builder.', ], - dryRun: false, }); const res = await request(await createApp({ diff --git a/server/src/services/company-skills.ts b/server/src/services/company-skills.ts index adeb537a..d1fea3d9 100644 --- a/server/src/services/company-skills.ts +++ b/server/src/services/company-skills.ts @@ -17,7 +17,6 @@ import type { CompanySkillImportResult, CompanySkillListItem, CompanySkillProjectScanConflict, - CompanySkillProjectScanPruned, CompanySkillProjectScanRequest, CompanySkillProjectScanResult, CompanySkillProjectScanSkipped, @@ -1861,10 +1860,8 @@ export function companySkillService(db: Db) { ? await projects.listByIds(companyId, input.projectIds) : await projects.list(companyId); const workspaceFilter = new Set(input.workspaceIds ?? []); - const dryRun = input.dryRun === true; const skipped: CompanySkillProjectScanSkipped[] = []; const conflicts: CompanySkillProjectScanConflict[] = []; - const pruned: CompanySkillProjectScanPruned[] = []; const warnings: string[] = []; const imported: CompanySkill[] = []; const updated: CompanySkill[] = []; @@ -2046,18 +2043,6 @@ export function companySkillService(db: Db) { for (const skill of skillsAtSource) { if (currentSlugs.has(skill.slug)) continue; const usedByAgents = await usage(companyId, skill.key); - const affectedAgentNames = usedByAgents.map((a) => a.name); - - pruned.push({ - skillId: skill.id, - slug: skill.slug, - key: skill.key, - sourceLocator: skill.sourceLocator, - affectedAgents: affectedAgentNames, - }); - - if (dryRun) continue; - if (usedByAgents.length > 0) { // Detach the skill from all agents that have it, then delete for (const agent of usedByAgents) { @@ -2074,7 +2059,7 @@ export function companySkillService(db: Db) { } } warnings.push( - `Skill "${skill.slug}" was removed from ${sourceLocator} and detached from ${affectedAgentNames.join(", ")}.`, + `Skill "${skill.slug}" was removed from ${sourceLocator} and detached from ${usedByAgents.map((a) => a.name).join(", ")}.`, ); } else { warnings.push( @@ -2097,9 +2082,7 @@ export function companySkillService(db: Db) { updated, skipped, conflicts, - pruned, warnings, - dryRun, }; }