diff --git a/docs/PLANO_SKILL_FABRIC.md b/docs/PLANO_SKILL_FABRIC.md new file mode 100644 index 0000000..4838e7c --- /dev/null +++ b/docs/PLANO_SKILL_FABRIC.md @@ -0,0 +1,1049 @@ + Vou criar um plano técnico focado apenas nas funções e implementações, sem aspectos de negócio, custos ou gestão de equipe. Ideal para gerar comandos no Claude Code. + +\--- + +\`\`\`markdown +\# PLANO TÉCNICO DE IMPLEMENTAÇÃO: SKILL FABRIC +\#\# Gerador e Gestor de Desenvolvimento de Skills \- Arcádia Suite + +\*\*Versão:\*\* 1.0 +\*\*Data:\*\* Março 2026 +\*\*Tipo:\*\* Especificação Técnica para Implementação + +\--- + +\#\# 1\. ARQUITETURA TÉCNICA + +\#\#\# 1.1 Stack Tecnológico + +| Camada | Tecnologia | Propósito | +|--------|-----------|-----------| +| Frontend | React \+ TypeScript \+ Monaco Editor | IDE no browser | +| Backend | Node.js \+ TypeScript | API e runtime | +| Compilador | ANTLR \+ AST | Parser de skills | +| Validação | ESLint \+ Custom Rules | Quality gates | +| Runtime | VM2 \+ Sandboxing | Execução segura | +| Storage | PostgreSQL \+ Neo4j | Dados e grafo | +| Cache | Redis | Performance | + +\#\#\# 1.2 Estrutura de Diretórios + +\`\`\` +server/modules/skill-fabric/ +├── src/ +│ ├── api/ +│ │ ├── routes/ +│ │ │ ├── skills.routes.ts +│ │ │ ├── compiler.routes.ts +│ │ │ ├── validator.routes.ts +│ │ │ └── marketplace.routes.ts +│ │ └── controllers/ +│ ├── core/ +│ │ ├── skill/ +│ │ │ ├── Skill.entity.ts +│ │ │ ├── Skill.repository.ts +│ │ │ └── Skill.service.ts +│ │ ├── compiler/ +│ │ │ ├── VisualCompiler.ts +│ │ │ ├── CodeCompiler.ts +│ │ │ ├── MarkdownCompiler.ts +│ │ │ └── AST/ +│ │ ├── validator/ +│ │ │ ├── ValidationPipeline.ts +│ │ │ ├── rules/ +│ │ │ │ ├── SyntaxRule.ts +│ │ │ │ ├── TypeRule.ts +│ │ │ │ ├── SecurityRule.ts +│ │ │ │ └── PerformanceRule.ts +│ │ ├── executor/ +│ │ │ ├── SkillExecutor.ts +│ │ │ ├── Sandbox.ts +│ │ │ └── ReferenceResolver.ts +│ │ └── lifecycle/ +│ │ ├── LifecycleManager.ts +│ │ └── StateMachine.ts +│ └── types/ +│ └── index.ts +└── tests/ + +client/src/modules/skill-fabric/ +├── visual-studio/ +│ ├── components/ +│ │ ├── Canvas.tsx +│ │ ├── NodePalette.tsx +│ │ ├── PropertyPanel.tsx +│ │ └── ConnectionLine.tsx +│ └── hooks/ +│ ├── useCanvas.ts +│ └── useDragDrop.ts +├── code-ide/ +│ ├── components/ +│ │ ├── MonacoEditor.tsx +│ │ ├── IntelliSenseProvider.ts +│ │ └── DebuggerPanel.tsx +│ └── templates/ +│ └── skill-template.ts +├── markdown-studio/ +│ ├── components/ +│ │ ├── MarkdownEditor.tsx +│ │ ├── AIAssistant.tsx +│ │ └── LivePreview.tsx +│ └── parser/ +│ └── MarkdownParser.ts +└── shared/ + ├── components/ + │ ├── SkillToolbar.tsx + │ ├── VersionSelector.tsx + │ └── ValidationPanel.tsx + └── utils/ + └── referenceParser.ts +\`\`\` + +\--- + +\#\# 2\. MÓDULOS DE IMPLEMENTAÇÃO + +\#\#\# 2.1 Módulo: Core API (skills.api) + +\*\*Arquivos:\*\* +\- \`server/modules/skill-fabric/src/api/routes/skills.routes.ts\` +\- \`server/modules/skill-fabric/src/api/controllers/skills.controller.ts\` + +\*\*Funções:\*\* + +\`\`\`typescript +// CRUD Básico +POST /api/skills // createSkill(dto: CreateSkillDTO) +GET /api/skills // listSkills(query: ListSkillsQuery) +GET /api/skills/:id // getSkill(id: string) +PUT /api/skills/:id // updateSkill(id: string, dto: UpdateSkillDTO) +DELETE /api/skills/:id // archiveSkill(id: string) + +// Compilação +POST /api/skills/:id/compile // compileSkill(id: string) +GET /api/skills/:id/ast // getSkillAST(id: string) + +// Validação +POST /api/skills/:id/validate // validateSkill(id: string) +GET /api/skills/:id/validation // getValidationResults(id: string) + +// Execução +POST /api/skills/:id/execute // executeSkill(id: string, input: any) +GET /api/skills/:id/executions // listExecutions(id: string) + +// Versionamento +GET /api/skills/:id/versions // listVersions(id: string) +POST /api/skills/:id/versions // createVersion(id: string, dto: VersionDTO) +POST /api/skills/:id/rollback // rollbackToVersion(id: string, version: string) + +// Lifecycle +POST /api/skills/:id/submit // submitForReview(id: string) +POST /api/skills/:id/approve // approveSkill(id: string) +POST /api/skills/:id/reject // rejectSkill(id: string, reason: string) +POST /api/skills/:id/publish // publishSkill(id: string) +POST /api/skills/:id/deprecate // deprecateSkill(id: string) + +// Marketplace +GET /api/skills/marketplace // listMarketplaceSkills(query: MarketplaceQuery) +POST /api/skills/:id/publish-marketplace // publishToMarketplace(id: string) +POST /api/skills/marketplace/:id/install // installFromMarketplace(id: string) +\`\`\` + +\*\*DTOs:\*\* + +\`\`\`typescript +interface CreateSkillDTO { + name: string; + slug: string; + description: string; + type: 'visual' | 'code' | 'markdown'; + tenantId: number; + companyId?: number; + initialContent?: any; +} + +interface UpdateSkillDTO { + name?: string; + description?: string; + content?: any; + metadata?: SkillMetadata; +} + +interface ListSkillsQuery { + tenantId?: number; + companyId?: number; + userId?: number; + type?: 'visual' | 'code' | 'markdown'; + status?: 'draft' | 'dev' | 'testing' | 'staging' | 'production'; + tags?: string\[\]; + search?: string; + limit?: number; + offset?: number; +} +\`\`\` + +\--- + +\#\#\# 2.2 Módulo: Skill Entity (skill.entity) + +\*\*Arquivo:\*\* \`server/modules/skill-fabric/src/core/skill/Skill.entity.ts\` + +\*\*Classe:\*\* + +\`\`\`typescript +export class Skill { + constructor(props: SkillProps) { + this.id \= props.id || uuid(); + this.validateProps(props); + Object.assign(this, props); + } + + // Identidade + id: UUID; + slug: string; + name: string; + description: string; + + // Hierarquia + tenantId: number; + companyId?: number; + userId?: number; + namespace: 'system' | 'tenant' | 'company' | 'user'; + + // Implementação + type: 'visual' | 'code' | 'markdown'; + content: VisualContent | CodeContent | MarkdownContent; + compiled?: CompiledSkill; + + // Interface + inputSchema: JSONSchema; + outputSchema: JSONSchema; + + // Runtime + timeout: number \= 30000; + memory: number \= 512; + retries: number \= 3; + + // Lifecycle + status: SkillStatus \= 'draft'; + version: SemanticVersion \= '0.0.1'; + branch: string \= 'main'; + + // Métodos de domínio + compile(): CompiledSkill; + validate(): ValidationResult; + execute(context: ExecutionContext): Promise\; + changeStatus(newStatus: SkillStatus, reason?: string): void; + createVersion(message: string): Version; + rollback(version: string): void; + fork(newSlug: string): Skill; + + // Validação + private validateProps(props: SkillProps): void; + private validateSlug(slug: string): boolean; + private validateContent(content: any): boolean; +} +\`\`\` + +\--- + +\#\#\# 2.3 Módulo: Compiladores (compiler) + +\*\*Arquivos:\*\* +\- \`server/modules/skill-fabric/src/core/compiler/VisualCompiler.ts\` +\- \`server/modules/skill-fabric/src/core/compiler/CodeCompiler.ts\` +\- \`server/modules/skill-fabric/src/core/compiler/MarkdownCompiler.ts\` + +\*\*Interface:\*\* + +\`\`\`typescript +interface Compiler { + compile(source: any): CompiledSkill; + parse(source: any): AST; + generateCode(ast: AST): string; + validateSyntax(source: any): SyntaxValidationResult; +} + +// Visual Compiler +export class VisualCompiler implements Compiler { + compile(canvas: VisualCanvas): CompiledSkill { + // 1\. Valida conexões + // 2\. Ordena topologicamente + // 3\. Gera AST + // 4\. Compila para JavaScript + } + + parse(canvas: VisualCanvas): VisualAST; + generateCode(ast: VisualAST): string; + validateSyntax(canvas: VisualCanvas): SyntaxValidationResult; +} + +// Code Compiler +export class CodeCompiler implements Compiler { + compile(sourceCode: string): CompiledSkill { + // 1\. Parse TypeScript + // 2\. Type checking + // 3\. Transform decorators + // 4\. Bundle dependencies + } + + parse(sourceCode: string): TypeScriptAST; + generateCode(ast: TypeScriptAST): string; + validateSyntax(sourceCode: string): SyntaxValidationResult; +} + +// Markdown Compiler +export class MarkdownCompiler implements Compiler { + compile(markdown: string): CompiledSkill { + // 1\. Parse frontmatter + // 2\. Extrair blocos de código + // 3\. Resolver referências /xxx/ + // 4\. Gerar JavaScript + } + + parse(markdown: string): MarkdownAST; + generateCode(ast: MarkdownAST): string; + validateSyntax(markdown: string): SyntaxValidationResult; +} +\`\`\` + +\*\*AST Types:\*\* + +\`\`\`typescript +interface AST { + type: 'skill'; + version: string; + metadata: SkillMetadata; + imports: ImportNode\[\]; + exports: ExportNode\[\]; + body: StatementNode\[\]; +} + +type StatementNode \= + | VariableDeclarationNode + | FunctionDeclarationNode + | ClassDeclarationNode + | ExpressionStatementNode + | IfStatementNode + | LoopStatementNode + | TryCatchNode + | SkillCallNode; + +interface SkillCallNode { + type: 'skill-call'; + reference: string; // /skill/xxx + arguments: ArgumentNode\[\]; + await: boolean; +} +\`\`\` + +\--- + +\#\#\# 2.4 Módulo: Validador (validator) + +\*\*Arquivo:\*\* \`server/modules/skill-fabric/src/core/validator/ValidationPipeline.ts\` + +\*\*Pipeline:\*\* + +\`\`\`typescript +export class ValidationPipeline { + private rules: ValidationRule\[\] \= \[ + new SyntaxRule(), + new TypeRule(), + new SecurityRule(), + new DependencyRule(), + new PerformanceRule(), + new DocumentationRule() + \]; + + async validate(skill: Skill): Promise\ { + const results: RuleResult\[\] \= \[\]; + + for (const rule of this.rules) { + const result \= await rule.check(skill); + results.push(result); + + // Fail fast para erros críticos + if (result.severity \=== 'error' && rule.isBlocking) { + break; + } + } + + return this.aggregateResults(results); + } + + calculateScore(results: RuleResult\[\]): number { + return results.reduce((score, r) \=\> { + return r.passed ? score \+ r.weight : score; + }, 0); + } +} + +// Regras individuais +export class SyntaxRule implements ValidationRule { + name \= 'syntax'; + weight \= 10; + isBlocking \= true; + + async check(skill: Skill): Promise\ { + const compiler \= this.getCompiler(skill.type); + const result \= compiler.validateSyntax(skill.content); + + return { + rule: this.name, + passed: result.valid, + weight: this.weight, + severity: result.valid ? 'info' : 'error', + details: result.errors + }; + } +} + +export class SecurityRule implements ValidationRule { + name \= 'security'; + weight \= 20; + isBlocking \= true; + + forbiddenPatterns \= \[ + /eval\\s\*\\(/, + /Function\\s\*\\(/, + /child\_process/, + /fs\\.unlink/, + /process\\.env\\s\*=/, + /\_\_proto\_\_/, + /constructor\\s\*\\\[\\s\*\["'\]prototype\["'\]\\s\*\\\]/ + \]; + + async check(skill: Skill): Promise\ { + const code \= skill.compiled?.code || ''; + const vulnerabilities: Vulnerability\[\] \= \[\]; + + for (const pattern of this.forbiddenPatterns) { + if (pattern.test(code)) { + vulnerabilities.push({ + severity: 'critical', + pattern: pattern.source, + line: this.findLine(code, pattern), + message: \`Uso proibido de: ${pattern.source}\` + }); + } + } + + // Scan de dependências + const deps \= skill.compiled?.dependencies || \[\]; + for (const dep of deps) { + const audit \= await this.auditDependency(dep); + if (audit.vulnerabilities.length \> 0\) { + vulnerabilities.push(...audit.vulnerabilities); + } + } + + return { + rule: this.name, + passed: vulnerabilities.length \=== 0, + weight: this.weight, + severity: vulnerabilities.length \> 0 ? 'error' : 'info', + details: vulnerabilities + }; + } +} +\`\`\` + +\--- + +\#\#\# 2.5 Módulo: Executor (executor) + +\*\*Arquivo:\*\* \`server/modules/skill-fabric/src/core/executor/SkillExecutor.ts\` + +\*\*Implementação:\*\* + +\`\`\`typescript +export class SkillExecutor { + constructor( + private sandbox: Sandbox, + private referenceResolver: ReferenceResolver, + private cache: CacheManager, + private logger: Logger + ) {} + + async execute( + skillId: string, + input: any, + context: ExecutionContext + ): Promise\ { + const skill \= await this.loadSkill(skillId); + + // Check cache + const cacheKey \= this.generateCacheKey(skillId, input); + if (\!context.skipCache) { + const cached \= await this.cache.get(cacheKey); + if (cached) return { ...cached, cached: true }; + } + + // Pre-execution + const validatedInput \= this.validateInput(skill, input); + const executionContext \= this.buildContext(skill, context); + + // Execute in sandbox + const startTime \= Date.now(); + try { + const result \= await this.sandbox.run({ + code: skill.compiled.code, + context: executionContext, + timeout: skill.timeout, + memory: skill.memory + }); + + // Post-execution + const duration \= Date.now() \- startTime; + const output \= this.validateOutput(skill, result); + + // Cache result + await this.cache.set(cacheKey, output, skill.cacheConfig); + + // Log execution + await this.logExecution(skill, input, output, duration); + + return { + success: true, + data: output, + duration, + executionId: context.executionId + }; + + } catch (error) { + // Handle error + if (skill.retries \> 0 && this.isRetryable(error)) { + return this.retry(skillId, input, context, skill.retries); + } + + // Fallback + if (skill.fallbackSkillId) { + return this.execute(skill.fallbackSkillId, input, context); + } + + return { + success: false, + error: this.sanitizeError(error), + duration: Date.now() \- startTime + }; + } + } + + private buildContext(skill: Skill, parentContext: ExecutionContext): ExecutionContext { + return { + ...parentContext, + skillId: skill.id, + tenantId: skill.tenantId, + variables: { + input: parentContext.input, + config: skill.config, + secrets: this.loadSecrets(skill.tenantId) + }, + skills: { + execute: (ref: string, params: any) \=\> this.executeReference(ref, params, parentContext) + }, + kg: { + query: (cypher: string, params: any) \=\> this.kg.query(cypher, params) + }, + tools: { + call: (toolName: string, params: any) \=\> this.callTool(toolName, params) + } + }; + } +} +\`\`\` + +\*\*Sandbox:\*\* + +\`\`\`typescript +export class Sandbox { + private vm: NodeVM; + + constructor(config: SandboxConfig) { + this.vm \= new NodeVM({ + timeout: config.timeout, + sandbox: config.context, + require: { + external: config.allowedModules || \[\], + builtin: \['path', 'util', 'crypto'\], + root: './', + mock: this.buildMocks() + }, + compiler: (code: string) \=\> this.compile(code) + }); + } + + async run(options: RunOptions): Promise\ { + const script \= new VMScript(options.code, { + filename: options.filename || 'skill.js' + }); + + const fn \= this.vm.run(script); + + if (typeof fn \=== 'function') { + return await fn(options.context); + } + + return fn; + } + + private buildMocks(): Record\ { + return { + fs: { + readFile: (path: string) \=\> { throw new Error('fs.readFile blocked'); }, + writeFile: () \=\> { throw new Error('fs.writeFile blocked'); } + }, + child\_process: new Proxy({}, { + get: () \=\> { throw new Error('child\_process blocked'); } + }) + }; + } +} +\`\`\` + +\--- + +\#\#\# 2.6 Módulo: Visual Studio (Frontend) + +\*\*Arquivo:\*\* \`client/src/modules/skill-fabric/visual-studio/components/Canvas.tsx\` + +\*\*Componentes:\*\* + +\`\`\`typescript +// Canvas principal +export const Canvas: React.FC\ \= ({ skill, onChange }) \=\> { + const \[nodes, setNodes\] \= useState\(skill.content.nodes); + const \[edges, setEdges\] \= useState\(skill.content.edges); + const \[selectedNode, setSelectedNode\] \= useState\(null); + + const { dragRef, dropRef, isDragging } \= useDragDrop({ + onDrop: (item, position) \=\> { + const newNode \= createNode(item.type, position); + setNodes(\[...nodes, newNode\]); + } + }); + + const onConnect \= (connection: Connection) \=\> { + const newEdge \= createEdge(connection); + if (validateConnection(newEdge, nodes, edges)) { + setEdges(\[...edges, newEdge\]); + } + }; + + const onNodeUpdate \= (nodeId: string, updates: Partial\) \=\> { + setNodes(nodes.map(n \=\> n.id \=== nodeId ? { ...n, ...updates } : n)); + }; + + const onCompile \= async () \=\> { + const compiled \= await compileVisualSkill({ nodes, edges }); + onChange({ ...skill, content: { nodes, edges }, compiled }); + }; + + return ( + \
+ \ + + \
+ \ + + \ setSelectedNode(node)} + nodeTypes={customNodeTypes} + edgeTypes={customEdgeTypes} + fitView + \> + \ + \ + \ + \ + + {selectedNode && ( + \ onNodeUpdate(selectedNode.id, updates)} + onClose={() \=\> setSelectedNode(null)} + /\> + )} + \ + \ + ); +}; + +// Tipos de nós disponíveis +const nodeTypes \= { + trigger: TriggerNode, + action: ActionNode, + condition: ConditionNode, + loop: LoopNode, + transform: TransformNode, + output: OutputNode +}; +\`\`\` + +\--- + +\#\#\# 2.7 Módulo: Code IDE (Frontend) + +\*\*Arquivo:\*\* \`client/src/modules/skill-fabric/code-ide/components/MonacoEditor.tsx\` + +\*\*Implementação:\*\* + +\`\`\`typescript +export const SkillCodeEditor: React.FC\ \= ({ skill, onChange }) \=\> { + const editorRef \= useRef\(); + const \[decorations, setDecorations\] \= useState\(\[\]); + + // Configurar IntelliSense para referências /xxx/ + useEffect(() \=\> { + if (\!editorRef.current) return; + + const disposable \= monaco.languages.registerCompletionItemProvider( + 'typescript', + { + triggerCharacters: \['/'\], + provideCompletionItems: async (model, position) \=\> { + const lineContent \= model.getLineContent(position.lineNumber); + const beforeCursor \= lineContent.substring(0, position.column \- 1); + + if (beforeCursor.match(/\\/(\\w\*)$/)) { + const suggestions \= await fetchReferenceSuggestions( + beforeCursor, + skill.tenantId + ); + + return { + suggestions: suggestions.map(s \=\> ({ + label: s.fullReference, + kind: monaco.languages.CompletionItemKind.Reference, + insertText: s.fullReference, + detail: s.description, + documentation: { value: s.documentation } + })) + }; + } + + return { suggestions: \[\] }; + } + } + ); + + return () \=\> disposable.dispose(); + }, \[skill.tenantId\]); + + // Real-time validation + const onValidate \= async (code: string) \=\> { + const markers \= await validateCode(code); + monaco.editor.setModelMarkers( + editorRef.current\!.getModel()\!, + 'skill-validator', + markers.map(m \=\> ({ + severity: monaco.MarkerSeverity\[m.severity\], + message: m.message, + startLineNumber: m.line, + startColumn: m.column, + endLineNumber: m.endLine || m.line, + endColumn: m.endColumn || m.column \+ 1 + })) + ); + }; + + return ( + \
+ \ executeSkill(skill.id, editorRef.current\!.getValue())} + onDebug={() \=\> startDebugger(skill.id)} + onFormat={() \=\> formatCode(editorRef.current\!)} + /\> + + \ { + editorRef.current \= editor; + configureSkillEditor(editor); + }} + options={{ + minimap: { enabled: true }, + folding: true, + automaticLayout: true, + suggestOnTriggerCharacters: true, + quickSuggestions: true + }} + /\> + + \ + \ + ); +}; +\`\`\` + +\--- + +\#\#\# 2.8 Módulo: Referências (reference) + +\*\*Arquivo:\*\* \`client/src/shared/utils/referenceParser.ts\` + +\*\*Parser:\*\* + +\`\`\`typescript +export class ReferenceParser { + // Padrão: /type:namespace/path?query + private static readonly PATTERN \= + /\\/(skill|kg|file|data|var|tool|agent)(?::(system|tenant|company|user))?\\/(\[a-zA-Z0-9\_\\/\\.\\-:\]+)(?:\\?(\[^\\s\]+))?/g; + + parse(text: string): Reference\[\] { + const refs: Reference\[\] \= \[\]; + let match; + + while ((match \= ReferenceParser.PATTERN.exec(text)) \!== null) { + const \[fullMatch, type, namespace, path, queryString\] \= match; + + refs.push({ + type: type as ReferenceType, + namespace: namespace as ReferenceNamespace, + path, + queryParams: queryString ? parseQueryString(queryString) : undefined, + fullMatch, + position: { + start: match.index, + end: match.index \+ fullMatch.length + } + }); + } + + return refs; + } + + async resolveReferences( + refs: Reference\[\], + context: ResolutionContext + ): Promise\ { + return Promise.all(refs.map(ref \=\> this.resolve(ref, context))); + } + + private async resolve(ref: Reference, context: ResolutionContext): Promise\ { + const resolvers: Record\ \= { + skill: new SkillResolver(), + kg: new KGResolver(), + file: new FileResolver(), + data: new DataResolver(), + var: new VariableResolver(), + tool: new ToolResolver(), + agent: new AgentResolver() + }; + + const resolver \= resolvers\[ref.type\]; + const value \= await resolver.resolve(ref, context); + + return { + ...ref, + resolved: true, + value, + metadata: await resolver.getMetadata(ref) + }; + } +} +\`\`\` + +\--- + +\#\# 3\. COMANDOS DE IMPLEMENTAÇÃO PARA CLAUDE CODE + +\#\#\# 3.1 Setup Inicial + +\`\`\`bash +\# Criar estrutura de diretórios +mkdir \-p server/modules/skill-fabric/src/{api/{routes,controllers},core/{skill,compiler,validator,executor,lifecycle},types} +mkdir \-p client/src/modules/skill-fabric/{visual-studio/{components,hooks},code-ide/{components,templates},markdown-studio/{components,parser},shared/{components,utils}} + +\# Instalar dependências backend +cd server/modules/skill-fabric +npm init \-y +npm install typescript @types/node ts-node express zod uuid vm2 antlr4ts +npm install \-D jest @types/jest supertest + +\# Instalar dependências frontend +cd ../../../client +npm install @monaco-editor/react react-flow-renderer @types/react-flow-renderer +npm install antlr4ts antlr4ts-cli + +\# Gerar parser ANTLR +npx antlr4ts \-visitor \-listener server/modules/skill-fabric/src/core/compiler/grammar/SkillLexer.g4 +npx antlr4ts \-visitor \-listener server/modules/skill-fabric/src/core/compiler/grammar/SkillParser.g4 +\`\`\` + +\#\#\# 3.2 Implementação por Fase + +\*\*Fase 1: Core API e Entity\*\* +\`\`\`bash +\# Gerar arquivos base +claude generate server/modules/skill-fabric/src/core/skill/Skill.entity.ts +claude generate server/modules/skill-fabric/src/core/skill/Skill.repository.ts +claude generate server/modules/skill-fabric/src/api/routes/skills.routes.ts +claude generate server/modules/skill-fabric/src/api/controllers/skills.controller.ts +\`\`\` + +\*\*Fase 2: Compiladores\*\* +\`\`\`bash +claude generate server/modules/skill-fabric/src/core/compiler/VisualCompiler.ts +claude generate server/modules/skill-fabric/src/core/compiler/CodeCompiler.ts +claude generate server/modules/skill-fabric/src/core/compiler/MarkdownCompiler.ts +\`\`\` + +\*\*Fase 3: Validador\*\* +\`\`\`bash +claude generate server/modules/skill-fabric/src/core/validator/ValidationPipeline.ts +claude generate server/modules/skill-fabric/src/core/validator/rules/SyntaxRule.ts +claude generate server/modules/skill-fabric/src/core/validator/rules/SecurityRule.ts +\`\`\` + +\*\*Fase 4: Executor\*\* +\`\`\`bash +claude generate server/modules/skill-fabric/src/core/executor/SkillExecutor.ts +claude generate server/modules/skill-fabric/src/core/executor/Sandbox.ts +claude generate server/modules/skill-fabric/src/core/executor/ReferenceResolver.ts +\`\`\` + +\*\*Fase 5: Frontend Visual\*\* +\`\`\`bash +claude generate client/src/modules/skill-fabric/visual-studio/components/Canvas.tsx +claude generate client/src/modules/skill-fabric/visual-studio/components/NodePalette.tsx +claude generate client/src/modules/skill-fabric/visual-studio/hooks/useDragDrop.ts +\`\`\` + +\*\*Fase 6: Frontend Code\*\* +\`\`\`bash +claude generate client/src/modules/skill-fabric/code-ide/components/MonacoEditor.tsx +claude generate client/src/modules/skill-fabric/code-ide/components/IntelliSenseProvider.ts +claude generate client/src/modules/skill-fabric/code-ide/templates/skill-template.ts +\`\`\` + +\--- + +\#\# 4\. TESTES + +\#\#\# 4.1 Estrutura de Testes + +\`\`\` +tests/ +├── unit/ +│ ├── skill.entity.test.ts +│ ├── visual-compiler.test.ts +│ ├── code-compiler.test.ts +│ ├── markdown-compiler.test.ts +│ ├── validation-pipeline.test.ts +│ └── skill-executor.test.ts +├── integration/ +│ ├── api.test.ts +│ ├── compile-execute.test.ts +│ └── reference-resolution.test.ts +└── e2e/ + ├── create-skill-flow.test.ts + ├── visual-editor.test.ts + └── marketplace.test.ts +\`\`\` + +\#\#\# 4.2 Exemplo de Teste + +\`\`\`typescript +// tests/unit/skill.entity.test.ts +describe('Skill Entity', () \=\> { + it('should create skill with valid props', () \=\> { + const skill \= new Skill({ + name: 'Test Skill', + slug: 'test\_skill', + type: 'code', + content: { sourceCode: 'export default () \=\> {}' }, + tenantId: 1 + }); + + expect(skill.id).toBeDefined(); + expect(skill.status).toBe('draft'); + expect(skill.version).toBe('0.0.1'); + }); + + it('should validate slug format', () \=\> { + expect(() \=\> new Skill({ slug: 'invalid slug' })).toThrow(); + expect(() \=\> new Skill({ slug: 'valid\_slug' })).not.toThrow(); + }); + + it('should compile skill', async () \=\> { + const skill \= createTestSkill('code'); + const compiled \= await skill.compile(); + + expect(compiled.code).toBeDefined(); + expect(compiled.ast).toBeDefined(); + expect(compiled.dependencies).toBeInstanceOf(Array); + }); +}); +\`\`\` + +\--- + +\#\# 5\. MIGRAÇÃO E DEPLOY + +\#\#\# 5.1 Migração de Dados + +\`\`\`typescript +// scripts/migrate-skills.ts +export async function migrateLegacySkills() { + const legacySkills \= await db.query('SELECT \* FROM old\_automations'); + + for (const old of legacySkills) { + const skill \= new Skill({ + name: old.name, + slug: generateSlug(old.name), + type: inferType(old), + content: convertContent(old), + tenantId: old.tenant\_id, + status: 'production' + }); + + await skillRepo.save(skill); + } +} +\`\`\` + +\#\#\# 5.2 Feature Flags + +\`\`\`typescript +// Configuração gradual +const featureFlags \= { + 'skill-fabric.enabled': true, + 'skill-fabric.visual-editor': true, + 'skill-fabric.code-ide': true, + 'skill-fabric.markdown-studio': false, // Beta + 'skill-fabric.marketplace': false // Próxima release +}; +\`\`\` + +\--- + +\*\*Fim do Plano Técnico\*\* +\`\`\` + +\--- + +Este plano técnico está pronto para gerar comandos no Claude Code. Ele contém: + +✅ \*\*Estrutura de diretórios\*\* completa +✅ \*\*Funções e métodos\*\* detalhados para cada módulo +✅ \*\*Interfaces e tipos\*\* TypeScript +✅ \*\*Comandos de implementação\*\* por fase +✅ \*\*Testes\*\* estruturados + +\*\*Para usar no Claude Code:\*\* +\`\`\`bash +\# Exemplo de comando +claude generate server/modules/skill-fabric/src/core/skill/Skill.entity.ts \--spec "Plano Técnico Skill Fabric v1.0" +\`\`\` + +Quer que eu gere comandos específicos para algum módulo ou adicione mais detalhes de implementação?