@onion-architect-ai/cli 4.1.0-beta.1 → 4.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +8 -19
- package/dist/cli.js.map +1 -1
- package/package.json +4 -3
- package/templates/.cursor/agents/compliance/iso-22301-specialist.md +917 -0
- package/templates/.cursor/agents/compliance/iso-27001-specialist.md +641 -0
- package/templates/.cursor/agents/compliance/pmbok-specialist.md +669 -0
- package/templates/.cursor/agents/compliance/security-information-master.md +824 -0
- package/templates/.cursor/agents/compliance/soc2-specialist.md +818 -0
- package/templates/.cursor/agents/deployment/docker-specialist.md +1192 -0
- package/templates/.cursor/agents/meta/agent-creator-specialist.md +1135 -0
- package/templates/.cursor/agents/meta/command-creator-specialist.md +1519 -0
- package/templates/.cursor/agents/meta/metaspec-gate-keeper.md +240 -0
- package/templates/.cursor/agents/meta/onion.md +753 -0
- package/templates/.cursor/agents/research/research-agent.md +292 -0
- package/templates/.cursor/agents/review/corporate-compliance-specialist.md +370 -0
- package/templates/.cursor/commands/common/prompts/README.md +187 -0
- package/templates/.cursor/commands/common/prompts/clickup-patterns.md +144 -0
- package/templates/.cursor/commands/common/prompts/code-review-checklist.md +168 -0
- package/templates/.cursor/commands/common/prompts/git-workflow-patterns.md +235 -0
- package/templates/.cursor/commands/common/prompts/output-formats.md +240 -0
- package/templates/.cursor/commands/common/prompts/technical.md +172 -0
- package/templates/.cursor/commands/common/prompts/validation-rules.md +173 -0
- package/templates/.cursor/commands/common/templates/abstraction-template.md +400 -0
- package/templates/.cursor/commands/common/templates/agent-template.md +353 -0
- package/templates/.cursor/commands/common/templates/business_context_template.md +748 -0
- package/templates/.cursor/commands/common/templates/command-template.md +273 -0
- package/templates/.cursor/commands/common/templates/technical_context_template.md +526 -0
- package/templates/.cursor/commands/development/runflow-dev.md +465 -0
- package/templates/.cursor/commands/docs/build-compliance-docs.md +143 -0
- package/templates/.cursor/commands/git/README.md +606 -0
- package/templates/.cursor/commands/meta/all-tools.md +50 -0
- package/templates/.cursor/commands/meta/analyze-complex-problem.md +186 -0
- package/templates/.cursor/commands/meta/create-abstraction.md +859 -0
- package/templates/.cursor/commands/meta/create-agent-express.md +83 -0
- package/templates/.cursor/commands/meta/create-agent.md +210 -0
- package/templates/.cursor/commands/meta/create-command.md +203 -0
- package/templates/.cursor/commands/meta/create-knowledge-base.md +143 -0
- package/templates/.cursor/commands/meta/create-task-structure.md +150 -0
- package/templates/.cursor/commands/meta/setup-integration.md +257 -0
- package/templates/.cursor/commands/onion/setup.md +843 -0
- package/templates/.cursor/commands/onion.md +168 -0
- package/templates/.cursor/commands/product/README.md +230 -0
- package/templates/.cursor/commands/quick/analisys.md +17 -0
- package/templates/.cursor/commands/validate/collab/pair-testing.md +633 -0
- package/templates/.cursor/commands/validate/collab/three-amigos.md +505 -0
- package/templates/.cursor/commands/validate/qa-points/estimate.md +660 -0
- package/templates/.cursor/commands/validate/test-strategy/analyze.md +1134 -0
- package/templates/.cursor/commands/validate/test-strategy/create.md +392 -0
- package/templates/.cursor/commands/validate/workflow.md +360 -0
- package/templates/.cursor/commands/warm-up.md +91 -0
- package/templates/.cursor/docs/architecture/acoplamento-clickup-problema-analise.md +446 -0
- package/templates/.cursor/docs/architecture/desacoplamento-roadmap.md +360 -0
- package/templates/.cursor/docs/architecture/validacao-fase-1.md +219 -0
- package/templates/.cursor/docs/c4/c4-detection-rules.md +395 -0
- package/templates/.cursor/docs/c4/c4-documentation-templates.md +579 -0
- package/templates/.cursor/docs/c4/c4-mermaid-patterns.md +331 -0
- package/templates/.cursor/docs/c4/c4-templates.md +256 -0
- package/templates/.cursor/docs/clickup/clickup-acceptance-criteria-strategy.md +329 -0
- package/templates/.cursor/docs/clickup/clickup-auto-update-strategy.md +318 -0
- package/templates/.cursor/docs/clickup/clickup-comment-formatter.md +239 -0
- package/templates/.cursor/docs/clickup/clickup-description-fix.md +355 -0
- package/templates/.cursor/docs/clickup/clickup-dual-comment-strategy.md +505 -0
- package/templates/.cursor/docs/clickup/clickup-formatting.md +302 -0
- package/templates/.cursor/docs/clickup/separador-tamanho-otimizado.md +256 -0
- package/templates/.cursor/docs/engineer/pre-pr-acceptance-validation.md +256 -0
- package/templates/.cursor/docs/onion/ESPERANTO.md +278 -0
- package/templates/.cursor/docs/onion/agents-reference.md +832 -0
- package/templates/.cursor/docs/onion/clickup-integration.md +738 -0
- package/templates/.cursor/docs/onion/commands-guide.md +807 -0
- package/templates/.cursor/docs/onion/engineering-flows.md +865 -0
- package/templates/.cursor/docs/onion/getting-started.md +741 -0
- package/templates/.cursor/docs/onion/maintenance-checklist.md +388 -0
- package/templates/.cursor/docs/onion/naming-conventions.md +268 -0
- package/templates/.cursor/docs/onion/practical-examples.md +782 -0
- package/templates/.cursor/docs/product/story-points-integration.md +254 -0
- package/templates/.cursor/docs/product/story-points-validation.md +224 -0
- package/templates/.cursor/docs/reviews/task-manager-docs-review-2025-11-24.md +167 -0
- package/templates/.cursor/docs/strategies/clickup-comment-patterns.md +766 -0
- package/templates/.cursor/docs/strategies/clickup-integration-tests.md +599 -0
- package/templates/.cursor/docs/strategies/clickup-mcp-wrappers-tests.md +854 -0
- package/templates/.cursor/docs/strategies/clickup-regression-tests.md +589 -0
- package/templates/.cursor/docs/strategies/visual-patterns.md +308 -0
- package/templates/.cursor/docs/templates/README.md +624 -0
- package/templates/.cursor/docs/templates/adr-template.md +226 -0
- package/templates/.cursor/docs/templates/analysis-template.md +280 -0
- package/templates/.cursor/docs/templates/execution-plan-template.md +430 -0
- package/templates/.cursor/docs/templates/guide-template.md +367 -0
- package/templates/.cursor/docs/templates/phase-execution-prompt-template.md +504 -0
- package/templates/.cursor/docs/templates/reference-template.md +522 -0
- package/templates/.cursor/docs/templates/solution-template.md +390 -0
- package/templates/.cursor/docs/tools/README.md +325 -0
- package/templates/.cursor/docs/tools/agents.md +330 -0
- package/templates/.cursor/docs/tools/commands.md +606 -0
- package/templates/.cursor/docs/tools/cursor.md +498 -0
- package/templates/.cursor/docs/tools/mcps.md +858 -0
- package/templates/.cursor/docs/tools/rules.md +423 -0
- package/templates/.cursor/rules/language-and-documentation.mdc +371 -0
- package/templates/.cursor/rules/onion-patterns.mdc +197 -0
- package/templates/.cursor/rules/validation-rules.mdc +194 -0
- package/templates/.cursor/utils/clickup-mcp-wrappers.md +671 -0
- package/templates/.cursor/utils/date-time-standards.md +182 -0
- package/templates/.cursor/utils/task-manager/README.md +94 -0
- package/templates/.cursor/utils/task-manager/adapters/asana.md +377 -0
- package/templates/.cursor/utils/task-manager/adapters/clickup.md +467 -0
- package/templates/.cursor/utils/task-manager/adapters/linear.md +421 -0
- package/templates/.cursor/utils/task-manager/detector.md +290 -0
- package/templates/.cursor/utils/task-manager/factory.md +363 -0
- package/templates/.cursor/utils/task-manager/interface.md +248 -0
- package/templates/.cursor/utils/task-manager/types.md +409 -0
- package/templates/.cursor/validation/product-task-validation.md +344 -0
- package/templates/.onion/contexts/business/.context-config.yml +52 -0
- package/templates/.onion/contexts/business/README.md +222 -0
- package/templates/.onion/contexts/business/agents/branding-specialist.md +1030 -0
- package/templates/.onion/contexts/business/agents/clickup-specialist.md +397 -0
- package/templates/.onion/contexts/business/agents/extract-meeting-specialist.md +395 -0
- package/templates/.onion/contexts/business/agents/gamma-specialist.md +1169 -0
- package/templates/.onion/contexts/business/agents/meeting-consolidator.md +483 -0
- package/templates/.onion/contexts/business/agents/pain-price-specialist.md +509 -0
- package/templates/.onion/contexts/business/agents/presentation-orchestrator.md +1191 -0
- package/templates/.onion/contexts/business/agents/product-agent.md +202 -0
- package/templates/.onion/contexts/business/agents/story-points-specialist.md +539 -0
- package/templates/.onion/contexts/business/agents/storytelling-specialist.md +891 -0
- package/templates/.onion/contexts/business/agents/task-specialist.md +618 -0
- package/templates/.onion/contexts/business/agents/whisper-specialist.md +373 -0
- package/templates/.onion/contexts/business/commands/advanced/analyze-pain-price.md +709 -0
- package/templates/.onion/contexts/business/commands/advanced/branding.md +460 -0
- package/templates/.onion/contexts/business/commands/advanced/checklist-sync.md +241 -0
- package/templates/.onion/contexts/business/commands/advanced/presentation.md +189 -0
- package/templates/.onion/contexts/business/commands/advanced/transform-consolidated.md +592 -0
- package/templates/.onion/contexts/business/commands/help.md +212 -0
- package/templates/.onion/contexts/business/commands/intermediate/check.md +48 -0
- package/templates/.onion/contexts/business/commands/intermediate/collect.md +96 -0
- package/templates/.onion/contexts/business/commands/intermediate/consolidate-meetings.md +306 -0
- package/templates/.onion/contexts/business/commands/intermediate/convert-to-tasks.md +220 -0
- package/templates/.onion/contexts/business/commands/intermediate/extract-meeting.md +241 -0
- package/templates/.onion/contexts/business/commands/intermediate/feature.md +431 -0
- package/templates/.onion/contexts/business/commands/intermediate/light-arch.md +97 -0
- package/templates/.onion/contexts/business/commands/intermediate/task-check.md +340 -0
- package/templates/.onion/contexts/business/commands/intermediate/validate-task.md +294 -0
- package/templates/.onion/contexts/business/commands/intermediate/whisper.md +325 -0
- package/templates/.onion/contexts/business/commands/starter/estimate.md +519 -0
- package/templates/.onion/contexts/business/commands/starter/refine.md +186 -0
- package/templates/.onion/contexts/business/commands/starter/spec.md +107 -0
- package/templates/.onion/contexts/business/commands/starter/task.md +585 -0
- package/templates/.onion/contexts/business/commands/starter/warm-up.md +187 -0
- package/templates/.onion/contexts/technical/.context-config.yml +64 -0
- package/templates/.onion/contexts/technical/README.md +238 -0
- package/templates/.onion/contexts/technical/agents/branch-code-reviewer.md +200 -0
- package/templates/.onion/contexts/technical/agents/branch-doc-writer.md +162 -0
- package/templates/.onion/contexts/technical/agents/branch-metaspec-checker.md +68 -0
- package/templates/.onion/contexts/technical/agents/branch-test-planner.md +177 -0
- package/templates/.onion/contexts/technical/agents/c4-architecture-specialist.md +712 -0
- package/templates/.onion/contexts/technical/agents/c4-documentation-specialist.md +658 -0
- package/templates/.onion/contexts/technical/agents/code-reviewer.md +155 -0
- package/templates/.onion/contexts/technical/agents/cursor-specialist.md +249 -0
- package/templates/.onion/contexts/technical/agents/docs-reverse-engineer.md +418 -0
- package/templates/.onion/contexts/technical/agents/gitflow-specialist.md +1207 -0
- package/templates/.onion/contexts/technical/agents/linux-security-specialist.md +676 -0
- package/templates/.onion/contexts/technical/agents/mermaid-specialist.md +516 -0
- package/templates/.onion/contexts/technical/agents/nodejs-specialist.md +673 -0
- package/templates/.onion/contexts/technical/agents/nx-migration-specialist.md +867 -0
- package/templates/.onion/contexts/technical/agents/nx-monorepo-specialist.md +619 -0
- package/templates/.onion/contexts/technical/agents/postgres-specialist.md +1124 -0
- package/templates/.onion/contexts/technical/agents/react-developer.md +132 -0
- package/templates/.onion/contexts/technical/agents/runflow-specialist.md +278 -0
- package/templates/.onion/contexts/technical/agents/system-doc-orchestrator.md +1388 -0
- package/templates/.onion/contexts/technical/agents/test-agent.md +425 -0
- package/templates/.onion/contexts/technical/agents/test-engineer.md +295 -0
- package/templates/.onion/contexts/technical/agents/test-planner.md +118 -0
- package/templates/.onion/contexts/technical/agents/zen-engine-specialist.md +421 -0
- package/templates/.onion/contexts/technical/commands/advanced/bump.md +43 -0
- package/templates/.onion/contexts/technical/commands/advanced/consolidate-documents.md +424 -0
- package/templates/.onion/contexts/technical/commands/advanced/e2e.md +392 -0
- package/templates/.onion/contexts/technical/commands/advanced/feature-finish.md +90 -0
- package/templates/.onion/contexts/technical/commands/advanced/feature-publish.md +91 -0
- package/templates/.onion/contexts/technical/commands/advanced/feature-start.md +158 -0
- package/templates/.onion/contexts/technical/commands/advanced/hotfix-finish.md +98 -0
- package/templates/.onion/contexts/technical/commands/advanced/hotfix-start.md +94 -0
- package/templates/.onion/contexts/technical/commands/advanced/hotfix.md +186 -0
- package/templates/.onion/contexts/technical/commands/advanced/refine-vision.md +27 -0
- package/templates/.onion/contexts/technical/commands/advanced/release-finish.md +98 -0
- package/templates/.onion/contexts/technical/commands/advanced/release-start.md +95 -0
- package/templates/.onion/contexts/technical/commands/advanced/reverse-consolidate.md +160 -0
- package/templates/.onion/contexts/technical/commands/advanced/validate-phase-sync.md +118 -0
- package/templates/.onion/contexts/technical/commands/help.md +329 -0
- package/templates/.onion/contexts/technical/commands/intermediate/build-business-docs.md +276 -0
- package/templates/.onion/contexts/technical/commands/intermediate/build-index.md +128 -0
- package/templates/.onion/contexts/technical/commands/intermediate/build-tech-docs.md +204 -0
- package/templates/.onion/contexts/technical/commands/intermediate/code-review.md +215 -0
- package/templates/.onion/contexts/technical/commands/intermediate/docs-health.md +142 -0
- package/templates/.onion/contexts/technical/commands/intermediate/fast-commit.md +45 -0
- package/templates/.onion/contexts/technical/commands/intermediate/integration.md +523 -0
- package/templates/.onion/contexts/technical/commands/intermediate/pr-update.md +198 -0
- package/templates/.onion/contexts/technical/commands/intermediate/pre-pr.md +91 -0
- package/templates/.onion/contexts/technical/commands/intermediate/start.md +266 -0
- package/templates/.onion/contexts/technical/commands/intermediate/sync-sessions.md +320 -0
- package/templates/.onion/contexts/technical/commands/intermediate/unit.md +378 -0
- package/templates/.onion/contexts/technical/commands/intermediate/validate-docs.md +159 -0
- package/templates/.onion/contexts/technical/commands/starter/docs.md +39 -0
- package/templates/.onion/contexts/technical/commands/starter/help.md +306 -0
- package/templates/.onion/contexts/technical/commands/starter/init.md +139 -0
- package/templates/.onion/contexts/technical/commands/starter/plan.md +111 -0
- package/templates/.onion/contexts/technical/commands/starter/pr.md +136 -0
- package/templates/.onion/contexts/technical/commands/starter/sync.md +228 -0
- package/templates/.onion/contexts/technical/commands/starter/warm-up.md +173 -0
- package/templates/.onion/contexts/technical/commands/starter/work.md +169 -0
- package/templates/.onion/core/commands/help.md +388 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# 🟣 Linear Adapter (Stub)
|
|
2
|
+
|
|
3
|
+
## 🎯 Propósito
|
|
4
|
+
|
|
5
|
+
Stub documentado para implementação futura do `ITaskManager` para Linear.
|
|
6
|
+
|
|
7
|
+
> ⚠️ **STUB**: Este adapter contém apenas a estrutura e documentação. A implementação completa requer desenvolvimento adicional.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📋 Configuração
|
|
12
|
+
|
|
13
|
+
### Variáveis de Ambiente
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Obrigatória
|
|
17
|
+
LINEAR_API_KEY=lin_api_xxxxx
|
|
18
|
+
|
|
19
|
+
# Opcionais
|
|
20
|
+
LINEAR_TEAM_ID=xxxxx-xxxxx-xxxxx # Team padrão
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Obter Token
|
|
24
|
+
|
|
25
|
+
1. Acesse Linear → Settings → API → Personal API Keys
|
|
26
|
+
2. Clique em "Create key"
|
|
27
|
+
3. Copie o token e adicione ao `.env`
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 📊 API do Linear
|
|
32
|
+
|
|
33
|
+
### Endpoint
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
https://api.linear.app/graphql
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Autenticação
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
Authorization: Bearer {LINEAR_API_KEY}
|
|
43
|
+
Content-Type: application/json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 🔧 Implementação (Stub)
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
/**
|
|
52
|
+
* Adapter Linear implementando ITaskManager.
|
|
53
|
+
*
|
|
54
|
+
* ⚠️ STUB: Métodos retornam notImplemented() por padrão.
|
|
55
|
+
* Para implementação completa, usar Linear GraphQL API.
|
|
56
|
+
*/
|
|
57
|
+
class LinearAdapter implements ITaskManager {
|
|
58
|
+
readonly provider: TaskManagerProvider = 'linear';
|
|
59
|
+
readonly isConfigured: boolean;
|
|
60
|
+
|
|
61
|
+
private apiKey: string;
|
|
62
|
+
private teamId?: string;
|
|
63
|
+
|
|
64
|
+
constructor(config: LinearAdapterConfig) {
|
|
65
|
+
this.apiKey = config.apiKey;
|
|
66
|
+
this.teamId = config.teamId;
|
|
67
|
+
this.isConfigured = !!this.apiKey;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
71
|
+
// CRUD DE TASKS (ISSUES)
|
|
72
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
73
|
+
|
|
74
|
+
async createTask(input: CreateTaskInput): Promise<TaskOutput> {
|
|
75
|
+
return this.notImplemented('createTask');
|
|
76
|
+
|
|
77
|
+
// TODO: Implementar usando GraphQL mutation
|
|
78
|
+
// mutation IssueCreate($input: IssueCreateInput!) {
|
|
79
|
+
// issueCreate(input: $input) {
|
|
80
|
+
// success
|
|
81
|
+
// issue {
|
|
82
|
+
// id
|
|
83
|
+
// identifier
|
|
84
|
+
// title
|
|
85
|
+
// url
|
|
86
|
+
// }
|
|
87
|
+
// }
|
|
88
|
+
// }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async getTask(taskId: string): Promise<TaskOutput> {
|
|
92
|
+
return this.notImplemented('getTask');
|
|
93
|
+
|
|
94
|
+
// TODO: Implementar usando GraphQL query
|
|
95
|
+
// query Issue($id: String!) {
|
|
96
|
+
// issue(id: $id) {
|
|
97
|
+
// id
|
|
98
|
+
// identifier
|
|
99
|
+
// title
|
|
100
|
+
// description
|
|
101
|
+
// state { name }
|
|
102
|
+
// priority
|
|
103
|
+
// url
|
|
104
|
+
// }
|
|
105
|
+
// }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async updateTask(taskId: string, updates: UpdateTaskInput): Promise<TaskOutput> {
|
|
109
|
+
return this.notImplemented('updateTask');
|
|
110
|
+
|
|
111
|
+
// TODO: Implementar usando GraphQL mutation
|
|
112
|
+
// mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
|
|
113
|
+
// issueUpdate(id: $id, input: $input) {
|
|
114
|
+
// success
|
|
115
|
+
// issue { id title }
|
|
116
|
+
// }
|
|
117
|
+
// }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async deleteTask(taskId: string): Promise<boolean> {
|
|
121
|
+
console.warn('⚠️ Linear.deleteTask() não implementado');
|
|
122
|
+
return false;
|
|
123
|
+
|
|
124
|
+
// TODO: Linear usa archive ao invés de delete
|
|
125
|
+
// mutation IssueArchive($id: String!) {
|
|
126
|
+
// issueArchive(id: $id) { success }
|
|
127
|
+
// }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
131
|
+
// SUBTASKS (SUB-ISSUES)
|
|
132
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
133
|
+
|
|
134
|
+
async createSubtask(parentId: string, input: CreateTaskInput): Promise<TaskOutput> {
|
|
135
|
+
return this.notImplemented('createSubtask');
|
|
136
|
+
|
|
137
|
+
// TODO: Usar parentId no mutation
|
|
138
|
+
// mutation IssueCreate($input: IssueCreateInput!) {
|
|
139
|
+
// issueCreate(input: { ...input, parentId: $parentId }) { ... }
|
|
140
|
+
// }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async getSubtasks(parentId: string): Promise<TaskOutput[]> {
|
|
144
|
+
console.warn('⚠️ Linear.getSubtasks() não implementado');
|
|
145
|
+
return [];
|
|
146
|
+
|
|
147
|
+
// TODO: Query children
|
|
148
|
+
// query Issue($id: String!) {
|
|
149
|
+
// issue(id: $id) {
|
|
150
|
+
// children { nodes { id title } }
|
|
151
|
+
// }
|
|
152
|
+
// }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
156
|
+
// COMENTÁRIOS
|
|
157
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
158
|
+
|
|
159
|
+
async addComment(taskId: string, comment: string): Promise<CommentOutput> {
|
|
160
|
+
return this.notImplemented('addComment');
|
|
161
|
+
|
|
162
|
+
// TODO: Mutation CommentCreate
|
|
163
|
+
// mutation CommentCreate($input: CommentCreateInput!) {
|
|
164
|
+
// commentCreate(input: { issueId: $taskId, body: $comment }) {
|
|
165
|
+
// success
|
|
166
|
+
// comment { id body }
|
|
167
|
+
// }
|
|
168
|
+
// }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async getComments(taskId: string): Promise<CommentOutput[]> {
|
|
172
|
+
console.warn('⚠️ Linear.getComments() não implementado');
|
|
173
|
+
return [];
|
|
174
|
+
|
|
175
|
+
// TODO: Query comments
|
|
176
|
+
// query Issue($id: String!) {
|
|
177
|
+
// issue(id: $id) {
|
|
178
|
+
// comments { nodes { id body user { name } } }
|
|
179
|
+
// }
|
|
180
|
+
// }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
184
|
+
// STATUS
|
|
185
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
186
|
+
|
|
187
|
+
async updateStatus(taskId: string, status: TaskStatus): Promise<TaskOutput> {
|
|
188
|
+
return this.notImplemented('updateStatus');
|
|
189
|
+
|
|
190
|
+
// TODO: Mapear status para stateId do Linear
|
|
191
|
+
// mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
|
|
192
|
+
// issueUpdate(id: $id, input: { stateId: $stateId }) { ... }
|
|
193
|
+
// }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
197
|
+
// BUSCA
|
|
198
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
199
|
+
|
|
200
|
+
async searchTasks(query: SearchQuery): Promise<TaskOutput[]> {
|
|
201
|
+
console.warn('⚠️ Linear.searchTasks() não implementado');
|
|
202
|
+
return [];
|
|
203
|
+
|
|
204
|
+
// TODO: Query issues com filtro
|
|
205
|
+
// query Issues($filter: IssueFilter) {
|
|
206
|
+
// issues(filter: $filter) {
|
|
207
|
+
// nodes { id identifier title }
|
|
208
|
+
// }
|
|
209
|
+
// }
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
213
|
+
// PROJETOS (TEAMS/PROJECTS)
|
|
214
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
215
|
+
|
|
216
|
+
async getProjectList(): Promise<ProjectOutput[]> {
|
|
217
|
+
console.warn('⚠️ Linear.getProjectList() não implementado');
|
|
218
|
+
return [];
|
|
219
|
+
|
|
220
|
+
// TODO: Query teams ou projects
|
|
221
|
+
// query Teams {
|
|
222
|
+
// teams { nodes { id name } }
|
|
223
|
+
// }
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async getProject(projectId: string): Promise<ProjectOutput> {
|
|
227
|
+
return this.notImplemented('getProject');
|
|
228
|
+
|
|
229
|
+
// TODO: Query team ou project
|
|
230
|
+
// query Team($id: String!) {
|
|
231
|
+
// team(id: $id) { id name description }
|
|
232
|
+
// }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
236
|
+
// VALIDAÇÃO
|
|
237
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
238
|
+
|
|
239
|
+
validateTaskId(taskId: string): boolean {
|
|
240
|
+
// Linear IDs:
|
|
241
|
+
// - Identifier format: ABC-123
|
|
242
|
+
// - UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
243
|
+
return /^[A-Z]+-\d+$/.test(taskId) ||
|
|
244
|
+
/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(taskId);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
getProviderFromTaskId(taskId: string): TaskManagerProvider | null {
|
|
248
|
+
return this.validateTaskId(taskId) ? 'linear' : null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
252
|
+
// HELPERS
|
|
253
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
254
|
+
|
|
255
|
+
private notImplemented(method: string): never {
|
|
256
|
+
throw new Error(
|
|
257
|
+
`❌ Linear.${method}() não implementado.\n` +
|
|
258
|
+
`💡 Este é um adapter STUB. Para implementação completa:\n` +
|
|
259
|
+
` 1. Consulte a documentação: https://developers.linear.app/\n` +
|
|
260
|
+
` 2. Implemente o método usando GraphQL API\n` +
|
|
261
|
+
` 3. Teste com sua conta Linear`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Helper para fazer requisições GraphQL ao Linear.
|
|
267
|
+
* Use este método ao implementar os métodos acima.
|
|
268
|
+
*/
|
|
269
|
+
private async graphql<T>(query: string, variables?: Record<string, any>): Promise<T> {
|
|
270
|
+
const response = await fetch('https://api.linear.app/graphql', {
|
|
271
|
+
method: 'POST',
|
|
272
|
+
headers: {
|
|
273
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
274
|
+
'Content-Type': 'application/json'
|
|
275
|
+
},
|
|
276
|
+
body: JSON.stringify({ query, variables })
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
if (!response.ok) {
|
|
280
|
+
throw new Error(`Linear API error: ${response.statusText}`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const result = await response.json();
|
|
284
|
+
|
|
285
|
+
if (result.errors) {
|
|
286
|
+
throw new Error(`Linear GraphQL error: ${result.errors[0].message}`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return result.data;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## 📊 Mapeamento de Conceitos
|
|
297
|
+
|
|
298
|
+
| Interface | Linear |
|
|
299
|
+
|-----------|--------|
|
|
300
|
+
| `project` | Team ou Project |
|
|
301
|
+
| `task` | Issue |
|
|
302
|
+
| `subtask` | Sub-issue (child) |
|
|
303
|
+
| `status` | State (workflow) |
|
|
304
|
+
| `comment` | Comment |
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## 🔄 Status Mapping (Exemplo)
|
|
309
|
+
|
|
310
|
+
| Interface | Linear State |
|
|
311
|
+
|-----------|--------------|
|
|
312
|
+
| `backlog` | Backlog |
|
|
313
|
+
| `todo` | Todo |
|
|
314
|
+
| `in_progress` | In Progress |
|
|
315
|
+
| `review` | In Review |
|
|
316
|
+
| `done` | Done |
|
|
317
|
+
| `canceled` | Canceled |
|
|
318
|
+
|
|
319
|
+
> ⚠️ Os estados do Linear são customizáveis por team. O mapeamento real depende da configuração do workspace.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## 📚 Referências para Implementação
|
|
324
|
+
|
|
325
|
+
### GraphQL Queries Úteis
|
|
326
|
+
|
|
327
|
+
#### Listar Issues
|
|
328
|
+
|
|
329
|
+
```graphql
|
|
330
|
+
query Issues($teamId: String!, $first: Int) {
|
|
331
|
+
team(id: $teamId) {
|
|
332
|
+
issues(first: $first) {
|
|
333
|
+
nodes {
|
|
334
|
+
id
|
|
335
|
+
identifier
|
|
336
|
+
title
|
|
337
|
+
description
|
|
338
|
+
state { name color }
|
|
339
|
+
priority
|
|
340
|
+
url
|
|
341
|
+
createdAt
|
|
342
|
+
updatedAt
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Criar Issue
|
|
350
|
+
|
|
351
|
+
```graphql
|
|
352
|
+
mutation IssueCreate($input: IssueCreateInput!) {
|
|
353
|
+
issueCreate(input: $input) {
|
|
354
|
+
success
|
|
355
|
+
issue {
|
|
356
|
+
id
|
|
357
|
+
identifier
|
|
358
|
+
title
|
|
359
|
+
url
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### Atualizar Issue
|
|
366
|
+
|
|
367
|
+
```graphql
|
|
368
|
+
mutation IssueUpdate($id: String!, $input: IssueUpdateInput!) {
|
|
369
|
+
issueUpdate(id: $id, input: $input) {
|
|
370
|
+
success
|
|
371
|
+
issue {
|
|
372
|
+
id
|
|
373
|
+
title
|
|
374
|
+
state { name }
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 🚀 Como Implementar
|
|
383
|
+
|
|
384
|
+
1. **Configurar ambiente**
|
|
385
|
+
```bash
|
|
386
|
+
LINEAR_API_KEY=lin_api_xxxxx
|
|
387
|
+
LINEAR_TEAM_ID=xxxxx
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
2. **Testar conexão**
|
|
391
|
+
```typescript
|
|
392
|
+
const adapter = new LinearAdapter({ apiKey: process.env.LINEAR_API_KEY });
|
|
393
|
+
const teams = await adapter.graphql(`query { teams { nodes { id name } } }`);
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
3. **Implementar métodos**
|
|
397
|
+
- Começar por `createTask` e `getTask`
|
|
398
|
+
- Adicionar `updateTask` e `updateStatus`
|
|
399
|
+
- Implementar `addComment` e `getComments`
|
|
400
|
+
- Por último, `searchTasks` e `getProjectList`
|
|
401
|
+
|
|
402
|
+
4. **Testar com comandos**
|
|
403
|
+
```bash
|
|
404
|
+
TASK_MANAGER_PROVIDER=linear
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## 📚 Referências
|
|
410
|
+
|
|
411
|
+
- [Linear API Docs](https://developers.linear.app/)
|
|
412
|
+
- [Linear GraphQL Explorer](https://linear.app/graphql)
|
|
413
|
+
- [Interface ITaskManager](../interface.md)
|
|
414
|
+
- [Types](../types.md)
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
**Versão**: 1.0.0 (Stub)
|
|
419
|
+
**Criado em**: 2025-11-24
|
|
420
|
+
**Status**: 📝 Documentado, aguardando implementação
|
|
421
|
+
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# 🔍 Detector de Provedor - Task Manager
|
|
2
|
+
|
|
3
|
+
## 🎯 Propósito
|
|
4
|
+
|
|
5
|
+
Detecta e valida o provedor de gerenciamento de tarefas configurado, além de identificar a origem de IDs de tasks para garantir compatibilidade.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📋 Funções Principais
|
|
10
|
+
|
|
11
|
+
### detectProvider()
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
/**
|
|
15
|
+
* Detecta o provedor configurado via variáveis de ambiente.
|
|
16
|
+
* @returns Configuração do provedor ativo
|
|
17
|
+
*/
|
|
18
|
+
function detectProvider(): ProviderConfig {
|
|
19
|
+
const provider = (process.env.TASK_MANAGER_PROVIDER || 'none') as TaskManagerProvider;
|
|
20
|
+
|
|
21
|
+
const configs: Record<TaskManagerProvider, ProviderConfig> = {
|
|
22
|
+
clickup: {
|
|
23
|
+
provider: 'clickup',
|
|
24
|
+
isConfigured: !!process.env.CLICKUP_API_TOKEN,
|
|
25
|
+
requiredEnvVars: ['CLICKUP_API_TOKEN'],
|
|
26
|
+
optionalEnvVars: ['CLICKUP_WORKSPACE_ID', 'CLICKUP_DEFAULT_LIST_ID'],
|
|
27
|
+
errorMessage: !process.env.CLICKUP_API_TOKEN
|
|
28
|
+
? '❌ CLICKUP_API_TOKEN não configurado. Execute /meta/setup-integration'
|
|
29
|
+
: undefined
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
asana: {
|
|
33
|
+
provider: 'asana',
|
|
34
|
+
isConfigured: !!process.env.ASANA_ACCESS_TOKEN,
|
|
35
|
+
requiredEnvVars: ['ASANA_ACCESS_TOKEN'],
|
|
36
|
+
optionalEnvVars: ['ASANA_WORKSPACE_ID', 'ASANA_DEFAULT_PROJECT_ID'],
|
|
37
|
+
errorMessage: !process.env.ASANA_ACCESS_TOKEN
|
|
38
|
+
? '❌ ASANA_ACCESS_TOKEN não configurado. Execute /meta/setup-integration'
|
|
39
|
+
: undefined
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
linear: {
|
|
43
|
+
provider: 'linear',
|
|
44
|
+
isConfigured: !!process.env.LINEAR_API_KEY,
|
|
45
|
+
requiredEnvVars: ['LINEAR_API_KEY'],
|
|
46
|
+
optionalEnvVars: ['LINEAR_TEAM_ID'],
|
|
47
|
+
errorMessage: !process.env.LINEAR_API_KEY
|
|
48
|
+
? '❌ LINEAR_API_KEY não configurado. Execute /meta/setup-integration'
|
|
49
|
+
: undefined
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
none: {
|
|
53
|
+
provider: 'none',
|
|
54
|
+
isConfigured: true, // Sempre "configurado" pois é o fallback
|
|
55
|
+
requiredEnvVars: [],
|
|
56
|
+
optionalEnvVars: [],
|
|
57
|
+
errorMessage: undefined
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return configs[provider] || configs.none;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
### detectProviderFromTaskId()
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
/**
|
|
71
|
+
* Detecta o provedor de origem baseado no formato do ID da task.
|
|
72
|
+
* @param taskId - ID da task a analisar
|
|
73
|
+
* @returns Provedor detectado ou null se formato desconhecido
|
|
74
|
+
*/
|
|
75
|
+
function detectProviderFromTaskId(taskId: string): TaskManagerProvider | null {
|
|
76
|
+
if (!taskId || typeof taskId !== 'string') {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const trimmedId = taskId.trim();
|
|
81
|
+
|
|
82
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
83
|
+
// CLICKUP
|
|
84
|
+
// Formato: alfanumérico, 9 caracteres (ex: 86adfe9eb, abc123def)
|
|
85
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
86
|
+
if (/^[a-z0-9]{9}$/i.test(trimmedId)) {
|
|
87
|
+
return 'clickup';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
91
|
+
// ASANA
|
|
92
|
+
// Formato: numérico, 16+ dígitos (ex: 1234567890123456)
|
|
93
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
94
|
+
if (/^\d{15,}$/.test(trimmedId)) {
|
|
95
|
+
return 'asana';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
99
|
+
// LINEAR
|
|
100
|
+
// Formatos:
|
|
101
|
+
// - Prefixo + número: ABC-123, PROJ-456
|
|
102
|
+
// - UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
103
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
104
|
+
if (/^[A-Z]+-\d+$/.test(trimmedId)) {
|
|
105
|
+
return 'linear';
|
|
106
|
+
}
|
|
107
|
+
if (/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(trimmedId)) {
|
|
108
|
+
return 'linear';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
112
|
+
// LOCAL (gerado pelo NoProviderAdapter)
|
|
113
|
+
// Formato: local-timestamp (ex: local-1732456789012)
|
|
114
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
115
|
+
if (/^local-\d+$/.test(trimmedId)) {
|
|
116
|
+
return 'none';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Formato desconhecido
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### validateProviderMatch()
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
/**
|
|
130
|
+
* Valida se um ID de task é compatível com o provedor configurado.
|
|
131
|
+
* @param taskId - ID da task a validar
|
|
132
|
+
* @param currentProvider - Provedor atualmente configurado
|
|
133
|
+
* @returns Resultado da validação com possível warning
|
|
134
|
+
*/
|
|
135
|
+
function validateProviderMatch(
|
|
136
|
+
taskId: string,
|
|
137
|
+
currentProvider: TaskManagerProvider
|
|
138
|
+
): ValidationResult {
|
|
139
|
+
const detectedProvider = detectProviderFromTaskId(taskId);
|
|
140
|
+
|
|
141
|
+
// Formato desconhecido - assumir válido
|
|
142
|
+
if (!detectedProvider) {
|
|
143
|
+
return {
|
|
144
|
+
valid: true,
|
|
145
|
+
warning: null,
|
|
146
|
+
detectedProvider: null
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Provedor 'none' aceita qualquer ID (modo offline)
|
|
151
|
+
if (currentProvider === 'none') {
|
|
152
|
+
return {
|
|
153
|
+
valid: true,
|
|
154
|
+
warning: `ℹ️ Task ID "${taskId}" detectado como ${detectedProvider}, ` +
|
|
155
|
+
`mas nenhum provedor está configurado. Operando em modo local.`,
|
|
156
|
+
detectedProvider
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Provedores diferentes - incompatibilidade
|
|
161
|
+
if (detectedProvider !== currentProvider) {
|
|
162
|
+
return {
|
|
163
|
+
valid: false,
|
|
164
|
+
warning: `⚠️ INCOMPATIBILIDADE DETECTADA\n` +
|
|
165
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
|
|
166
|
+
`Task ID: "${taskId}"\n` +
|
|
167
|
+
`Provedor detectado: ${detectedProvider}\n` +
|
|
168
|
+
`Provedor configurado: ${currentProvider}\n\n` +
|
|
169
|
+
`💡 Ações sugeridas:\n` +
|
|
170
|
+
` 1. Altere TASK_MANAGER_PROVIDER para '${detectedProvider}' no .env\n` +
|
|
171
|
+
` 2. Ou limpe a sessão atual e crie uma nova task\n` +
|
|
172
|
+
` 3. Execute /meta/setup-integration para reconfigurar`,
|
|
173
|
+
detectedProvider
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Tudo OK
|
|
178
|
+
return {
|
|
179
|
+
valid: true,
|
|
180
|
+
warning: null,
|
|
181
|
+
detectedProvider
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### checkProviderConfiguration()
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
/**
|
|
192
|
+
* Verifica a configuração completa do provedor.
|
|
193
|
+
* @returns Objeto com status e mensagens
|
|
194
|
+
*/
|
|
195
|
+
function checkProviderConfiguration(): {
|
|
196
|
+
provider: TaskManagerProvider;
|
|
197
|
+
isConfigured: boolean;
|
|
198
|
+
missingVars: string[];
|
|
199
|
+
optionalVars: { name: string; set: boolean }[];
|
|
200
|
+
message: string;
|
|
201
|
+
} {
|
|
202
|
+
const config = detectProvider();
|
|
203
|
+
|
|
204
|
+
const missingVars = config.requiredEnvVars.filter(
|
|
205
|
+
varName => !process.env[varName]
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const optionalVars = config.optionalEnvVars.map(varName => ({
|
|
209
|
+
name: varName,
|
|
210
|
+
set: !!process.env[varName]
|
|
211
|
+
}));
|
|
212
|
+
|
|
213
|
+
let message: string;
|
|
214
|
+
|
|
215
|
+
if (config.provider === 'none') {
|
|
216
|
+
message = `ℹ️ Nenhum gerenciador de tarefas configurado.\n` +
|
|
217
|
+
`Comandos funcionarão em modo offline.\n` +
|
|
218
|
+
`Execute /meta/setup-integration para configurar.`;
|
|
219
|
+
} else if (!config.isConfigured) {
|
|
220
|
+
message = `❌ ${config.provider.toUpperCase()} selecionado mas não configurado.\n` +
|
|
221
|
+
`Variáveis faltando: ${missingVars.join(', ')}\n` +
|
|
222
|
+
`Execute /meta/setup-integration para configurar.`;
|
|
223
|
+
} else {
|
|
224
|
+
const optionalStatus = optionalVars
|
|
225
|
+
.map(v => ` ${v.set ? '✅' : '⚪'} ${v.name}`)
|
|
226
|
+
.join('\n');
|
|
227
|
+
|
|
228
|
+
message = `✅ ${config.provider.toUpperCase()} configurado corretamente.\n` +
|
|
229
|
+
`Variáveis opcionais:\n${optionalStatus}`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
provider: config.provider,
|
|
234
|
+
isConfigured: config.isConfigured,
|
|
235
|
+
missingVars,
|
|
236
|
+
optionalVars,
|
|
237
|
+
message
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 📊 Tabela de Formatos de ID
|
|
245
|
+
|
|
246
|
+
| Provedor | Formato | Regex | Exemplo |
|
|
247
|
+
|----------|---------|-------|---------|
|
|
248
|
+
| ClickUp | 9 chars alfanuméricos | `^[a-z0-9]{9}$` | `86adfe9eb` |
|
|
249
|
+
| Asana | 15+ dígitos | `^\d{15,}$` | `1234567890123456` |
|
|
250
|
+
| Linear (ID) | PREFIXO-NUMERO | `^[A-Z]+-\d+$` | `DEV-123` |
|
|
251
|
+
| Linear (UUID) | UUID v4 | UUID regex | `a1b2c3d4-...` |
|
|
252
|
+
| Local | local-timestamp | `^local-\d+$` | `local-1732456789` |
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## 🧪 Exemplos de Uso
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
// Detectar provedor configurado
|
|
260
|
+
const config = detectProvider();
|
|
261
|
+
console.log(`Provedor: ${config.provider}`);
|
|
262
|
+
console.log(`Configurado: ${config.isConfigured}`);
|
|
263
|
+
|
|
264
|
+
// Validar ID de task
|
|
265
|
+
const taskId = '86adfe9eb';
|
|
266
|
+
const currentProvider = 'asana';
|
|
267
|
+
const validation = validateProviderMatch(taskId, currentProvider);
|
|
268
|
+
|
|
269
|
+
if (!validation.valid) {
|
|
270
|
+
console.warn(validation.warning);
|
|
271
|
+
// Perguntar ao usuário o que fazer
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Verificar configuração completa
|
|
275
|
+
const status = checkProviderConfiguration();
|
|
276
|
+
console.log(status.message);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## 📚 Referências
|
|
282
|
+
|
|
283
|
+
- [Types](./types.md) - Definições de tipos
|
|
284
|
+
- [Factory](./factory.md) - Criação de adapters
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
**Versão**: 1.0.0
|
|
289
|
+
**Criado em**: 2025-11-24
|
|
290
|
+
|