Merge pull request #1655 from paperclipai/pr/pap-795-company-portability

feat(portability): improve company import and export flow
This commit is contained in:
Dotta 2026-03-23 19:45:05 -05:00 committed by GitHub
commit eeb7e1a91a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 5238 additions and 271 deletions

View file

@ -253,9 +253,13 @@ export type {
CompanyPortabilityEnvInput,
CompanyPortabilityFileEntry,
CompanyPortabilityCompanyManifestEntry,
CompanyPortabilitySidebarOrder,
CompanyPortabilityAgentManifestEntry,
CompanyPortabilitySkillManifestEntry,
CompanyPortabilityProjectManifestEntry,
CompanyPortabilityProjectWorkspaceManifestEntry,
CompanyPortabilityIssueRoutineTriggerManifestEntry,
CompanyPortabilityIssueRoutineManifestEntry,
CompanyPortabilityIssueManifestEntry,
CompanyPortabilityManifest,
CompanyPortabilityExportResult,
@ -484,6 +488,7 @@ export {
portabilityIncludeSchema,
portabilityEnvInputSchema,
portabilityCompanyManifestEntrySchema,
portabilitySidebarOrderSchema,
portabilityAgentManifestEntrySchema,
portabilityManifestSchema,
portabilitySourceSchema,

View file

@ -33,6 +33,11 @@ export interface CompanyPortabilityCompanyManifestEntry {
requireBoardApprovalForNewAgents: boolean;
}
export interface CompanyPortabilitySidebarOrder {
agents: string[];
projects: string[];
}
export interface CompanyPortabilityProjectManifestEntry {
slug: string;
name: string;
@ -44,18 +49,52 @@ export interface CompanyPortabilityProjectManifestEntry {
color: string | null;
status: string | null;
executionWorkspacePolicy: Record<string, unknown> | null;
workspaces: CompanyPortabilityProjectWorkspaceManifestEntry[];
metadata: Record<string, unknown> | null;
}
export interface CompanyPortabilityProjectWorkspaceManifestEntry {
key: string;
name: string;
sourceType: string | null;
repoUrl: string | null;
repoRef: string | null;
defaultRef: string | null;
visibility: string | null;
setupCommand: string | null;
cleanupCommand: string | null;
metadata: Record<string, unknown> | null;
isPrimary: boolean;
}
export interface CompanyPortabilityIssueRoutineTriggerManifestEntry {
kind: string;
label: string | null;
enabled: boolean;
cronExpression: string | null;
timezone: string | null;
signingMode: string | null;
replayWindowSec: number | null;
}
export interface CompanyPortabilityIssueRoutineManifestEntry {
concurrencyPolicy: string | null;
catchUpPolicy: string | null;
triggers: CompanyPortabilityIssueRoutineTriggerManifestEntry[];
}
export interface CompanyPortabilityIssueManifestEntry {
slug: string;
identifier: string | null;
title: string;
path: string;
projectSlug: string | null;
projectWorkspaceKey: string | null;
assigneeAgentSlug: string | null;
description: string | null;
recurrence: Record<string, unknown> | null;
recurring: boolean;
routine: CompanyPortabilityIssueRoutineManifestEntry | null;
legacyRecurrence: Record<string, unknown> | null;
status: string | null;
priority: string | null;
labelIds: string[];
@ -110,6 +149,7 @@ export interface CompanyPortabilityManifest {
} | null;
includes: CompanyPortabilityInclude;
company: CompanyPortabilityCompanyManifestEntry | null;
sidebar: CompanyPortabilitySidebarOrder | null;
agents: CompanyPortabilityAgentManifestEntry[];
skills: CompanyPortabilitySkillManifestEntry[];
projects: CompanyPortabilityProjectManifestEntry[];
@ -245,6 +285,13 @@ export interface CompanyPortabilityImportResult {
name: string;
reason: string | null;
}[];
projects: {
slug: string;
id: string | null;
action: "created" | "updated" | "skipped";
name: string;
reason: string | null;
}[];
envInputs: CompanyPortabilityEnvInput[];
warnings: string[];
}
@ -258,4 +305,5 @@ export interface CompanyPortabilityExportRequest {
projectIssues?: string[];
selectedFiles?: string[];
expandReferencedSkills?: boolean;
sidebarOrder?: Partial<CompanyPortabilitySidebarOrder>;
}

View file

@ -144,9 +144,13 @@ export type {
CompanyPortabilityEnvInput,
CompanyPortabilityFileEntry,
CompanyPortabilityCompanyManifestEntry,
CompanyPortabilitySidebarOrder,
CompanyPortabilityAgentManifestEntry,
CompanyPortabilitySkillManifestEntry,
CompanyPortabilityProjectManifestEntry,
CompanyPortabilityProjectWorkspaceManifestEntry,
CompanyPortabilityIssueRoutineTriggerManifestEntry,
CompanyPortabilityIssueRoutineManifestEntry,
CompanyPortabilityIssueManifestEntry,
CompanyPortabilityManifest,
CompanyPortabilityExportResult,

View file

@ -38,6 +38,11 @@ export const portabilityCompanyManifestEntrySchema = z.object({
requireBoardApprovalForNewAgents: z.boolean(),
});
export const portabilitySidebarOrderSchema = z.object({
agents: z.array(z.string().min(1)).default([]),
projects: z.array(z.string().min(1)).default([]),
});
export const portabilityAgentManifestEntrySchema = z.object({
slug: z.string().min(1),
name: z.string().min(1),
@ -85,18 +90,50 @@ export const portabilityProjectManifestEntrySchema = z.object({
color: z.string().nullable(),
status: z.string().nullable(),
executionWorkspacePolicy: z.record(z.unknown()).nullable(),
workspaces: z.array(z.object({
key: z.string().min(1),
name: z.string().min(1),
sourceType: z.string().nullable(),
repoUrl: z.string().nullable(),
repoRef: z.string().nullable(),
defaultRef: z.string().nullable(),
visibility: z.string().nullable(),
setupCommand: z.string().nullable(),
cleanupCommand: z.string().nullable(),
metadata: z.record(z.unknown()).nullable(),
isPrimary: z.boolean(),
})).default([]),
metadata: z.record(z.unknown()).nullable(),
});
export const portabilityIssueRoutineTriggerManifestEntrySchema = z.object({
kind: z.string().min(1),
label: z.string().nullable(),
enabled: z.boolean(),
cronExpression: z.string().nullable(),
timezone: z.string().nullable(),
signingMode: z.string().nullable(),
replayWindowSec: z.number().int().nullable(),
});
export const portabilityIssueRoutineManifestEntrySchema = z.object({
concurrencyPolicy: z.string().nullable(),
catchUpPolicy: z.string().nullable(),
triggers: z.array(portabilityIssueRoutineTriggerManifestEntrySchema).default([]),
});
export const portabilityIssueManifestEntrySchema = z.object({
slug: z.string().min(1),
identifier: z.string().min(1).nullable(),
title: z.string().min(1),
path: z.string().min(1),
projectSlug: z.string().min(1).nullable(),
projectWorkspaceKey: z.string().min(1).nullable(),
assigneeAgentSlug: z.string().min(1).nullable(),
description: z.string().nullable(),
recurrence: z.record(z.unknown()).nullable(),
recurring: z.boolean().default(false),
routine: portabilityIssueRoutineManifestEntrySchema.nullable(),
legacyRecurrence: z.record(z.unknown()).nullable(),
status: z.string().nullable(),
priority: z.string().nullable(),
labelIds: z.array(z.string().min(1)).default([]),
@ -123,6 +160,7 @@ export const portabilityManifestSchema = z.object({
skills: z.boolean(),
}),
company: portabilityCompanyManifestEntrySchema.nullable(),
sidebar: portabilitySidebarOrderSchema.nullable(),
agents: z.array(portabilityAgentManifestEntrySchema),
skills: z.array(portabilitySkillManifestEntrySchema).default([]),
projects: z.array(portabilityProjectManifestEntrySchema).default([]),
@ -169,6 +207,7 @@ export const companyPortabilityExportSchema = z.object({
projectIssues: z.array(z.string().min(1)).optional(),
selectedFiles: z.array(z.string().min(1)).optional(),
expandReferencedSkills: z.boolean().optional(),
sidebarOrder: portabilitySidebarOrderSchema.partial().optional(),
});
export type CompanyPortabilityExport = z.infer<typeof companyPortabilityExportSchema>;

View file

@ -60,6 +60,7 @@ export {
portabilityIncludeSchema,
portabilityEnvInputSchema,
portabilityCompanyManifestEntrySchema,
portabilitySidebarOrderSchema,
portabilityAgentManifestEntrySchema,
portabilitySkillManifestEntrySchema,
portabilityManifestSchema,