planflow-plugin 0.1.0

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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/bin/cli.js +169 -0
  4. package/bin/postinstall.js +87 -0
  5. package/commands/pfActivity/SKILL.md +725 -0
  6. package/commands/pfAssign/SKILL.md +623 -0
  7. package/commands/pfCloudLink/SKILL.md +192 -0
  8. package/commands/pfCloudList/SKILL.md +222 -0
  9. package/commands/pfCloudNew/SKILL.md +187 -0
  10. package/commands/pfCloudUnlink/SKILL.md +152 -0
  11. package/commands/pfComment/SKILL.md +227 -0
  12. package/commands/pfComments/SKILL.md +159 -0
  13. package/commands/pfConnectionStatus/SKILL.md +433 -0
  14. package/commands/pfDiscord/SKILL.md +740 -0
  15. package/commands/pfGithubBranch/SKILL.md +672 -0
  16. package/commands/pfGithubIssue/SKILL.md +963 -0
  17. package/commands/pfGithubLink/SKILL.md +859 -0
  18. package/commands/pfGithubPr/SKILL.md +1335 -0
  19. package/commands/pfGithubUnlink/SKILL.md +401 -0
  20. package/commands/pfLive/SKILL.md +185 -0
  21. package/commands/pfLogin/SKILL.md +249 -0
  22. package/commands/pfLogout/SKILL.md +155 -0
  23. package/commands/pfMyTasks/SKILL.md +198 -0
  24. package/commands/pfNotificationSettings/SKILL.md +619 -0
  25. package/commands/pfNotifications/SKILL.md +420 -0
  26. package/commands/pfNotificationsClear/SKILL.md +421 -0
  27. package/commands/pfReact/SKILL.md +232 -0
  28. package/commands/pfSlack/SKILL.md +659 -0
  29. package/commands/pfSyncPull/SKILL.md +210 -0
  30. package/commands/pfSyncPush/SKILL.md +299 -0
  31. package/commands/pfSyncStatus/SKILL.md +212 -0
  32. package/commands/pfTeamInvite/SKILL.md +161 -0
  33. package/commands/pfTeamList/SKILL.md +253 -0
  34. package/commands/pfTeamRemove/SKILL.md +115 -0
  35. package/commands/pfTeamRole/SKILL.md +160 -0
  36. package/commands/pfTestWebhooks/SKILL.md +722 -0
  37. package/commands/pfUnassign/SKILL.md +134 -0
  38. package/commands/pfWhoami/SKILL.md +258 -0
  39. package/commands/pfWorkload/SKILL.md +219 -0
  40. package/commands/planExportCsv/SKILL.md +106 -0
  41. package/commands/planExportGithub/SKILL.md +222 -0
  42. package/commands/planExportJson/SKILL.md +159 -0
  43. package/commands/planExportSummary/SKILL.md +158 -0
  44. package/commands/planNew/SKILL.md +641 -0
  45. package/commands/planNext/SKILL.md +1200 -0
  46. package/commands/planSettingsAutoSync/SKILL.md +199 -0
  47. package/commands/planSettingsLanguage/SKILL.md +201 -0
  48. package/commands/planSettingsReset/SKILL.md +237 -0
  49. package/commands/planSettingsShow/SKILL.md +482 -0
  50. package/commands/planSpec/SKILL.md +929 -0
  51. package/commands/planUpdate/SKILL.md +2518 -0
  52. package/commands/team/SKILL.md +740 -0
  53. package/locales/en.json +1499 -0
  54. package/locales/ka.json +1499 -0
  55. package/package.json +48 -0
  56. package/templates/PROJECT_PLAN.template.md +157 -0
  57. package/templates/backend-api.template.md +562 -0
  58. package/templates/frontend-spa.template.md +610 -0
  59. package/templates/fullstack.template.md +397 -0
  60. package/templates/ka/backend-api.template.md +562 -0
  61. package/templates/ka/frontend-spa.template.md +610 -0
  62. package/templates/ka/fullstack.template.md +397 -0
  63. package/templates/sections/architecture.md +21 -0
  64. package/templates/sections/overview.md +15 -0
  65. package/templates/sections/tasks.md +22 -0
  66. package/templates/sections/tech-stack.md +19 -0
@@ -0,0 +1,740 @@
1
+ ---
2
+ name: team
3
+ description: View and manage team members for the current PlanFlow project
4
+ ---
5
+
6
+ # Team Management
7
+
8
+ A unified command for viewing team members, inviting new members, and managing roles in the linked cloud project.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ /team # List all team members
14
+ /team add <email> # Invite with default role (editor)
15
+ /team add <email> <role> # Invite with specific role
16
+ /team role <email> <role> # Change member's role
17
+ ```
18
+
19
+ ## Available Roles
20
+
21
+ | Role | Permissions |
22
+ |------|-------------|
23
+ | `admin` | Full access, can manage team members |
24
+ | `editor` | Can edit tasks and plan (default) |
25
+ | `viewer` | Read-only access |
26
+
27
+ ## Step 0: Load Configuration
28
+
29
+ ```javascript
30
+ function getConfig() {
31
+ const localConfigPath = "./.plan-config.json"
32
+ let localConfig = {}
33
+ if (fileExists(localConfigPath)) {
34
+ try { localConfig = JSON.parse(readFile(localConfigPath)) } catch {}
35
+ }
36
+
37
+ const globalConfigPath = expandPath("~/.config/claude/plan-plugin-config.json")
38
+ let globalConfig = {}
39
+ if (fileExists(globalConfigPath)) {
40
+ try { globalConfig = JSON.parse(readFile(globalConfigPath)) } catch {}
41
+ }
42
+
43
+ return {
44
+ ...globalConfig,
45
+ ...localConfig,
46
+ cloud: {
47
+ ...(globalConfig.cloud || {}),
48
+ ...(localConfig.cloud || {})
49
+ }
50
+ }
51
+ }
52
+
53
+ const config = getConfig()
54
+ const language = config.language || "en"
55
+ const cloudConfig = config.cloud || {}
56
+ const isAuthenticated = !!cloudConfig.apiToken
57
+ const projectId = cloudConfig.projectId
58
+ const apiUrl = cloudConfig.apiUrl || "https://api.planflow.tools"
59
+
60
+ const t = JSON.parse(readFile(`locales/${language}.json`))
61
+ ```
62
+
63
+ ## Step 0.5: Show Notification Badge (v1.6.0+)
64
+
65
+ **Purpose:** Display unread notification count to keep users informed of team activity.
66
+
67
+ **When to Execute:** Only if authenticated AND linked to a project.
68
+
69
+ ```bash
70
+ # Only proceed if authenticated and linked
71
+ if [ -n "$TOKEN" ] && [ -n "$PROJECT_ID" ]; then
72
+ RESPONSE=$(curl -s --connect-timeout 3 --max-time 5 \
73
+ -X GET \
74
+ -H "Accept: application/json" \
75
+ -H "Authorization: Bearer $TOKEN" \
76
+ "${API_URL}/projects/${PROJECT_ID}/notifications?limit=1&unread=true" 2>/dev/null)
77
+
78
+ if [ $? -eq 0 ]; then
79
+ UNREAD_COUNT=$(echo "$RESPONSE" | grep -o '"unreadCount":[0-9]*' | grep -o '[0-9]*')
80
+ if [ -n "$UNREAD_COUNT" ] && [ "$UNREAD_COUNT" -gt 0 ]; then
81
+ echo "🔔 $UNREAD_COUNT unread notification(s) — /pfNotifications to view"
82
+ echo ""
83
+ fi
84
+ fi
85
+ fi
86
+ ```
87
+
88
+ See: `skills/notification-badge/SKILL.md` for full implementation details.
89
+
90
+ ## Step 1: Validate Authentication
91
+
92
+ If not authenticated, display error card:
93
+
94
+ ```
95
+ ╭──────────────────────────────────────────────────────────────────────────────╮
96
+ │ ❌ ERROR │
97
+ ├──────────────────────────────────────────────────────────────────────────────┤
98
+ │ │
99
+ │ {t.commands.sync.notAuthenticated} │
100
+ │ │
101
+ │ 💡 {t.ui.labels.nextSteps} │
102
+ │ • /pfLogin Sign in to PlanFlow │
103
+ │ │
104
+ ╰──────────────────────────────────────────────────────────────────────────────╯
105
+ ```
106
+
107
+ ## Step 2: Validate Project Link
108
+
109
+ If no project is linked, display error card:
110
+
111
+ ```
112
+ ╭──────────────────────────────────────────────────────────────────────────────╮
113
+ │ ❌ ERROR │
114
+ ├──────────────────────────────────────────────────────────────────────────────┤
115
+ │ │
116
+ │ {t.commands.sync.notLinked} │
117
+ │ │
118
+ │ 💡 {t.ui.labels.nextSteps} │
119
+ │ • /pfCloudLink Link to a cloud project │
120
+ │ │
121
+ ╰──────────────────────────────────────────────────────────────────────────────╯
122
+ ```
123
+
124
+ ## Step 3: Parse Arguments
125
+
126
+ Parse the command arguments to determine the subcommand:
127
+
128
+ ```javascript
129
+ const args = commandArgs.trim()
130
+ const parts = args.split(/\s+/)
131
+
132
+ // Determine action
133
+ let action = "list" // default
134
+ let email = null
135
+ let role = null
136
+
137
+ if (parts.length === 0 || parts[0] === "" || parts[0] === "list") {
138
+ action = "list"
139
+ } else if (parts[0] === "add") {
140
+ action = "add"
141
+ email = parts[1]
142
+ role = parts[2] || "editor"
143
+ } else if (parts[0] === "role") {
144
+ action = "role"
145
+ email = parts[1]
146
+ role = parts[2]
147
+ } else {
148
+ // Unknown subcommand - show usage
149
+ action = "usage"
150
+ }
151
+ ```
152
+
153
+ ## Step 4: Route to Action
154
+
155
+ Based on the parsed action, execute the appropriate flow.
156
+
157
+ ### Action: usage (Unknown Command)
158
+
159
+ ```
160
+ ╭──────────────────────────────────────────────────────────────────────────────╮
161
+ │ 👥 Team Management │
162
+ ├──────────────────────────────────────────────────────────────────────────────┤
163
+ │ │
164
+ │ ── Usage ───────────────────────────────────────────────────────────────── │
165
+ │ │
166
+ │ /team List all team members │
167
+ │ /team add <email> Invite with default role (editor) │
168
+ │ /team add <email> <role> Invite with specific role │
169
+ │ /team role <email> <role> Change member's role │
170
+ │ │
171
+ │ ── Available Roles ─────────────────────────────────────────────────────── │
172
+ │ │
173
+ │ admin - Full access, can manage team members │
174
+ │ editor - Can edit tasks and plan (default) │
175
+ │ viewer - Read-only access │
176
+ │ │
177
+ │ ── Examples ────────────────────────────────────────────────────────────── │
178
+ │ │
179
+ │ /team │
180
+ │ /team add alice@company.com │
181
+ │ /team add bob@company.com admin │
182
+ │ /team role bob@company.com viewer │
183
+ │ │
184
+ ╰──────────────────────────────────────────────────────────────────────────────╯
185
+ ```
186
+
187
+ ---
188
+
189
+ ### Action: list (Default)
190
+
191
+ Fetch and display team members.
192
+
193
+ **API Call:**
194
+ ```bash
195
+ curl -s \
196
+ -H "Authorization: Bearer {TOKEN}" \
197
+ -H "Accept: application/json" \
198
+ "https://api.planflow.tools/projects/{PROJECT_ID}/team"
199
+ ```
200
+
201
+ **Success Card:**
202
+
203
+ ```
204
+ ╭──────────────────────────────────────────────────────────────────────────────╮
205
+ │ 👥 {t.commands.team.title} │
206
+ ├──────────────────────────────────────────────────────────────────────────────┤
207
+ │ │
208
+ │ 📁 {t.commands.team.project}: {projectName} │
209
+ │ │
210
+ │ ── Active Members ({count}) ──────────────────────────────────────────── │
211
+ │ │
212
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
213
+ │ │ 🟢 John Doe ({t.commands.team.roles.owner}) │ │
214
+ │ │ john@company.com │ │
215
+ │ │ {t.commands.team.workingOn}: T2.1 - API endpoints │ │
216
+ │ └────────────────────────────────────────────────────────────────────────┘ │
217
+ │ │
218
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
219
+ │ │ 🟢 Jane Smith ({t.commands.team.roles.admin}) │ │
220
+ │ │ jane@company.com │ │
221
+ │ │ {t.commands.team.workingOn}: T3.5 - Dashboard │ │
222
+ │ └────────────────────────────────────────────────────────────────────────┘ │
223
+ │ │
224
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
225
+ │ │ 🔴 Bob Wilson ({t.commands.team.roles.editor}) │ │
226
+ │ │ bob@company.com │ │
227
+ │ │ {t.commands.team.lastSeen}: 2 hours ago │ │
228
+ │ └────────────────────────────────────────────────────────────────────────┘ │
229
+ │ │
230
+ │ ── {t.commands.team.pendingInvites} ({inviteCount}) ──────────────────── │
231
+ │ │
232
+ │ ⏳ alice@company.com (Editor) - sent 2 days ago │
233
+ │ │
234
+ ├──────────────────────────────────────────────────────────────────────────────┤
235
+ │ │
236
+ │ 💡 {t.commands.team.commands} │
237
+ │ • /team add <email> {t.commands.team.inviteHint} │
238
+ │ • /team role <email> <role> {t.commands.team.roleHint} │
239
+ │ │
240
+ ╰──────────────────────────────────────────────────────────────────────────────╯
241
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
242
+ ```
243
+
244
+ **Only Owner (Empty Team) Card:**
245
+
246
+ ```
247
+ ╭──────────────────────────────────────────────────────────────────────────────╮
248
+ │ 👥 {t.commands.team.title} │
249
+ ├──────────────────────────────────────────────────────────────────────────────┤
250
+ │ │
251
+ │ 📁 {t.commands.team.project}: {projectName} │
252
+ │ │
253
+ │ ── Active Members (1) ────────────────────────────────────────────────── │
254
+ │ │
255
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
256
+ │ │ 🟢 You ({t.commands.team.roles.owner}) │ │
257
+ │ │ your@email.com │ │
258
+ │ └────────────────────────────────────────────────────────────────────────┘ │
259
+ │ │
260
+ │ ℹ️ {t.commands.team.onlyYou} │
261
+ │ │
262
+ ├──────────────────────────────────────────────────────────────────────────────┤
263
+ │ │
264
+ │ 💡 {t.commands.team.invitePrompt} │
265
+ │ • /team add <email> │
266
+ │ • /team add <email> admin (with role) │
267
+ │ │
268
+ ╰──────────────────────────────────────────────────────────────────────────────╯
269
+ ```
270
+
271
+ ---
272
+
273
+ ### Action: add (Invite Team Member)
274
+
275
+ Invite a new team member to the project.
276
+
277
+ **Validation:**
278
+
279
+ 1. Check email format:
280
+ ```javascript
281
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
282
+ if (!emailRegex.test(email)) {
283
+ // Show invalid email error
284
+ }
285
+ ```
286
+
287
+ 2. Check role is valid:
288
+ ```javascript
289
+ const validRoles = ["admin", "editor", "viewer"]
290
+ if (!validRoles.includes(role.toLowerCase())) {
291
+ // Show invalid role error
292
+ }
293
+ ```
294
+
295
+ **API Call:**
296
+ ```bash
297
+ curl -s -X POST \
298
+ -H "Authorization: Bearer {TOKEN}" \
299
+ -H "Content-Type: application/json" \
300
+ -H "Accept: application/json" \
301
+ -d '{"email": "{EMAIL}", "role": "{ROLE}"}' \
302
+ "https://api.planflow.tools/projects/{PROJECT_ID}/team/invite"
303
+ ```
304
+
305
+ **Success Card:**
306
+
307
+ ```
308
+ ╭──────────────────────────────────────────────────────────────────────────────╮
309
+ │ ✅ SUCCESS │
310
+ ├──────────────────────────────────────────────────────────────────────────────┤
311
+ │ │
312
+ │ {t.commands.team.invite.success} │
313
+ │ │
314
+ │ ── Invitation Details ──────────────────────────────────────────────────── │
315
+ │ │
316
+ │ 📧 {t.commands.team.invite.to} {email} │
317
+ │ 🔑 {t.commands.team.invite.role} {Role} │
318
+ │ 📁 {t.commands.team.invite.project} {projectName} │
319
+ │ │
320
+ │ ╭────────────────────╮ │
321
+ │ │ ✓ Invitation Sent │ │
322
+ │ ╰────────────────────╯ │
323
+ │ │
324
+ │ {t.commands.team.invite.emailSent} │
325
+ │ {t.commands.team.invite.expiresHint} │
326
+ │ │
327
+ ├──────────────────────────────────────────────────────────────────────────────┤
328
+ │ │
329
+ │ 💡 {t.ui.labels.commands} │
330
+ │ • /team View pending invitations │
331
+ │ │
332
+ ╰──────────────────────────────────────────────────────────────────────────────╯
333
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
334
+ ```
335
+
336
+ **Invalid Email Card:**
337
+
338
+ ```
339
+ ╭──────────────────────────────────────────────────────────────────────────────╮
340
+ │ ❌ ERROR │
341
+ ├──────────────────────────────────────────────────────────────────────────────┤
342
+ │ │
343
+ │ {t.commands.team.invite.invalidEmail} │
344
+ │ │
345
+ │ {t.commands.team.invite.emailExample} │
346
+ │ │
347
+ ╰──────────────────────────────────────────────────────────────────────────────╯
348
+ ```
349
+
350
+ **Invalid Role Card:**
351
+
352
+ ```
353
+ ╭──────────────────────────────────────────────────────────────────────────────╮
354
+ │ ❌ ERROR │
355
+ ├──────────────────────────────────────────────────────────────────────────────┤
356
+ │ │
357
+ │ {t.commands.team.invite.invalidRole}: {providedRole} │
358
+ │ │
359
+ │ {t.commands.team.invite.validRoles}: admin, editor, viewer │
360
+ │ │
361
+ ╰──────────────────────────────────────────────────────────────────────────────╯
362
+ ```
363
+
364
+ **Already Member Card (409):**
365
+
366
+ ```
367
+ ╭──────────────────────────────────────────────────────────────────────────────╮
368
+ │ ⚠️ WARNING │
369
+ ├──────────────────────────────────────────────────────────────────────────────┤
370
+ │ │
371
+ │ {t.commands.team.invite.alreadyMember} │
372
+ │ │
373
+ │ {email} {t.commands.team.invite.alreadyMemberHint} │
374
+ │ │
375
+ │ 💡 To change their role: │
376
+ │ • /team role {email} <role> │
377
+ │ │
378
+ ╰──────────────────────────────────────────────────────────────────────────────╯
379
+ ```
380
+
381
+ **Permission Denied Card (403):**
382
+
383
+ ```
384
+ ╭──────────────────────────────────────────────────────────────────────────────╮
385
+ │ ❌ ERROR │
386
+ ├──────────────────────────────────────────────────────────────────────────────┤
387
+ │ │
388
+ │ {t.commands.team.invite.noPermission} │
389
+ │ │
390
+ │ {t.commands.team.invite.noPermissionHint} │
391
+ │ │
392
+ ╰──────────────────────────────────────────────────────────────────────────────╯
393
+ ```
394
+
395
+ **Missing Email Card:**
396
+
397
+ ```
398
+ ╭──────────────────────────────────────────────────────────────────────────────╮
399
+ │ 📨 Team Invite │
400
+ ├──────────────────────────────────────────────────────────────────────────────┤
401
+ │ │
402
+ │ ── {t.commands.team.invite.usage} ──────────────────────────────────────── │
403
+ │ │
404
+ │ /team add <email> {t.commands.team.invite.usageDefault} │
405
+ │ /team add <email> <role> {t.commands.team.invite.usageWithRole} │
406
+ │ │
407
+ │ ── {t.commands.team.invite.availableRoles} ─────────────────────────────── │
408
+ │ │
409
+ │ admin - {t.commands.team.invite.roleAdminDesc} │
410
+ │ editor - {t.commands.team.invite.roleEditorDesc} │
411
+ │ viewer - {t.commands.team.invite.roleViewerDesc} │
412
+ │ │
413
+ │ ── {t.commands.team.invite.example} ────────────────────────────────────── │
414
+ │ │
415
+ │ /team add alice@company.com │
416
+ │ /team add bob@company.com admin │
417
+ │ │
418
+ ╰──────────────────────────────────────────────────────────────────────────────╯
419
+ ```
420
+
421
+ ---
422
+
423
+ ### Action: role (Change Member Role)
424
+
425
+ Change an existing team member's role.
426
+
427
+ **Validation:**
428
+
429
+ 1. Check email is provided
430
+ 2. Check role is provided
431
+ 3. Check role is valid
432
+
433
+ **API Call:**
434
+ ```bash
435
+ curl -s -X PATCH \
436
+ -H "Authorization: Bearer {TOKEN}" \
437
+ -H "Content-Type: application/json" \
438
+ -H "Accept: application/json" \
439
+ -d '{"role": "{ROLE}"}' \
440
+ "https://api.planflow.tools/projects/{PROJECT_ID}/team/{EMAIL}/role"
441
+ ```
442
+
443
+ **Success Card:**
444
+
445
+ ```
446
+ ╭──────────────────────────────────────────────────────────────────────────────╮
447
+ │ ✅ SUCCESS │
448
+ ├──────────────────────────────────────────────────────────────────────────────┤
449
+ │ │
450
+ │ {t.commands.team.role.success} │
451
+ │ │
452
+ │ ── Role Change Details ─────────────────────────────────────────────────── │
453
+ │ │
454
+ │ 👤 {t.commands.team.role.member}: {memberName} │
455
+ │ 📧 {t.commands.team.role.email}: {email} │
456
+ │ 📁 {t.commands.team.role.project}: {projectName} │
457
+ │ │
458
+ │ ╭─────────────────────────────────╮ │
459
+ │ │ {oldRole} → {newRole} │ │
460
+ │ ╰─────────────────────────────────╯ │
461
+ │ │
462
+ │ {t.commands.team.role.effectiveImmediately} │
463
+ │ │
464
+ ├──────────────────────────────────────────────────────────────────────────────┤
465
+ │ │
466
+ │ 💡 {t.ui.labels.commands} │
467
+ │ • /team View all team members │
468
+ │ │
469
+ ╰──────────────────────────────────────────────────────────────────────────────╯
470
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
471
+ ```
472
+
473
+ **Cannot Change Own Role Card:**
474
+
475
+ ```
476
+ ╭──────────────────────────────────────────────────────────────────────────────╮
477
+ │ ❌ ERROR │
478
+ ├──────────────────────────────────────────────────────────────────────────────┤
479
+ │ │
480
+ │ {t.commands.team.role.cannotChangeOwnRole} │
481
+ │ │
482
+ │ {t.commands.team.role.cannotChangeOwnRoleHint} │
483
+ │ │
484
+ ╰──────────────────────────────────────────────────────────────────────────────╯
485
+ ```
486
+
487
+ **Cannot Change Owner's Role Card (403):**
488
+
489
+ ```
490
+ ╭──────────────────────────────────────────────────────────────────────────────╮
491
+ │ ❌ ERROR │
492
+ ├──────────────────────────────────────────────────────────────────────────────┤
493
+ │ │
494
+ │ {t.commands.team.role.cannotChangeOwnerRole} │
495
+ │ │
496
+ │ {t.commands.team.role.cannotChangeOwnerRoleHint} │
497
+ │ │
498
+ ╰──────────────────────────────────────────────────────────────────────────────╯
499
+ ```
500
+
501
+ **Member Not Found Card (404):**
502
+
503
+ ```
504
+ ╭──────────────────────────────────────────────────────────────────────────────╮
505
+ │ ❌ ERROR │
506
+ ├──────────────────────────────────────────────────────────────────────────────┤
507
+ │ │
508
+ │ {t.commands.team.role.notFound} │
509
+ │ │
510
+ │ {email} {t.commands.team.role.notFoundHint} │
511
+ │ │
512
+ │ 💡 {t.commands.team.role.viewTeam} │
513
+ │ │
514
+ ╰──────────────────────────────────────────────────────────────────────────────╯
515
+ ```
516
+
517
+ **Invalid Role Card:**
518
+
519
+ ```
520
+ ╭──────────────────────────────────────────────────────────────────────────────╮
521
+ │ ❌ ERROR │
522
+ ├──────────────────────────────────────────────────────────────────────────────┤
523
+ │ │
524
+ │ {t.commands.team.role.invalidRole}: {providedRole} │
525
+ │ │
526
+ │ {t.commands.team.role.validRoles}: admin, editor, viewer │
527
+ │ │
528
+ ╰──────────────────────────────────────────────────────────────────────────────╯
529
+ ```
530
+
531
+ **Same Role Card (No Change):**
532
+
533
+ ```
534
+ ╭──────────────────────────────────────────────────────────────────────────────╮
535
+ │ ℹ️ INFO │
536
+ ├──────────────────────────────────────────────────────────────────────────────┤
537
+ │ │
538
+ │ {t.commands.team.role.sameRole} │
539
+ │ │
540
+ │ {email} {t.commands.team.role.alreadyHasRole} {role} │
541
+ │ │
542
+ ╰──────────────────────────────────────────────────────────────────────────────╯
543
+ ```
544
+
545
+ **Missing Arguments Card:**
546
+
547
+ ```
548
+ ╭──────────────────────────────────────────────────────────────────────────────╮
549
+ │ 🔑 {t.commands.team.role.title} │
550
+ ├──────────────────────────────────────────────────────────────────────────────┤
551
+ │ │
552
+ │ ── {t.commands.team.role.usage} ────────────────────────────────────────── │
553
+ │ │
554
+ │ /team role <email> <role> │
555
+ │ │
556
+ │ ── {t.commands.team.role.availableRoles} ───────────────────────────────── │
557
+ │ │
558
+ │ admin - {t.commands.team.invite.roleAdminDesc} │
559
+ │ editor - {t.commands.team.invite.roleEditorDesc} │
560
+ │ viewer - {t.commands.team.invite.roleViewerDesc} │
561
+ │ │
562
+ │ ── {t.commands.team.role.example} ──────────────────────────────────────── │
563
+ │ │
564
+ │ /team role bob@company.com viewer │
565
+ │ /team role alice@company.com admin │
566
+ │ │
567
+ ╰──────────────────────────────────────────────────────────────────────────────╯
568
+ ```
569
+
570
+ ---
571
+
572
+ ## Error Handling
573
+
574
+ **Network Error Card:**
575
+
576
+ ```
577
+ ╭──────────────────────────────────────────────────────────────────────────────╮
578
+ │ ❌ ERROR │
579
+ ├──────────────────────────────────────────────────────────────────────────────┤
580
+ │ │
581
+ │ {t.commands.team.networkError} │
582
+ │ │
583
+ │ Please check your connection and try again. │
584
+ │ │
585
+ ╰──────────────────────────────────────────────────────────────────────────────╯
586
+ ```
587
+
588
+ **API Error (403 Forbidden):**
589
+
590
+ ```
591
+ ╭──────────────────────────────────────────────────────────────────────────────╮
592
+ │ ❌ ERROR │
593
+ ├──────────────────────────────────────────────────────────────────────────────┤
594
+ │ │
595
+ │ {t.commands.team.noPermission} │
596
+ │ │
597
+ │ Only project members can view the team list. │
598
+ │ │
599
+ ╰──────────────────────────────────────────────────────────────────────────────╯
600
+ ```
601
+
602
+ **Authentication Failed (401):**
603
+
604
+ ```
605
+ ╭──────────────────────────────────────────────────────────────────────────────╮
606
+ │ ❌ ERROR │
607
+ ├──────────────────────────────────────────────────────────────────────────────┤
608
+ │ │
609
+ │ {t.commands.team.authFailed} │
610
+ │ │
611
+ │ 💡 Please run /pfLogin to re-authenticate. │
612
+ │ │
613
+ ╰──────────────────────────────────────────────────────────────────────────────╯
614
+ ```
615
+
616
+ ---
617
+
618
+ ## Response Parsing
619
+
620
+ ### Team List Response
621
+
622
+ ```json
623
+ {
624
+ "success": true,
625
+ "data": {
626
+ "project": {
627
+ "id": "uuid",
628
+ "name": "Project Name"
629
+ },
630
+ "members": [
631
+ {
632
+ "id": "uuid",
633
+ "email": "john@company.com",
634
+ "name": "John Doe",
635
+ "role": "owner",
636
+ "status": "active",
637
+ "currentTask": {
638
+ "taskId": "T2.1",
639
+ "name": "API endpoints"
640
+ },
641
+ "lastSeen": "2024-01-15T10:30:00Z"
642
+ }
643
+ ],
644
+ "pendingInvites": [
645
+ {
646
+ "email": "alice@company.com",
647
+ "role": "editor",
648
+ "sentAt": "2024-01-13T10:00:00Z"
649
+ }
650
+ ]
651
+ }
652
+ }
653
+ ```
654
+
655
+ ### Invite Response
656
+
657
+ ```json
658
+ {
659
+ "success": true,
660
+ "data": {
661
+ "invitation": {
662
+ "email": "alice@company.com",
663
+ "role": "editor",
664
+ "expiresAt": "2024-01-22T10:00:00Z"
665
+ }
666
+ }
667
+ }
668
+ ```
669
+
670
+ ### Role Change Response
671
+
672
+ ```json
673
+ {
674
+ "success": true,
675
+ "data": {
676
+ "member": {
677
+ "email": "bob@company.com",
678
+ "name": "Bob Wilson",
679
+ "previousRole": "editor",
680
+ "newRole": "viewer"
681
+ }
682
+ }
683
+ }
684
+ ```
685
+
686
+ ---
687
+
688
+ ## Implementation Notes
689
+
690
+ 1. **Role Capitalization**: Display roles with first letter capitalized (Editor, Admin, Viewer)
691
+ 2. **Online Status**: Use 🟢 for active (seen within 5 minutes), 🔴 for offline
692
+ 3. **Time Formatting**: Use relative time (e.g., "2 hours ago", "3 days ago")
693
+ 4. **Current User Highlight**: Show "You" instead of name for the current user
694
+ 5. **Email Validation**: Use standard email regex before API call
695
+ 6. **Role Validation**: Check against valid roles before API call
696
+
697
+ ---
698
+
699
+ ## Georgian Translation Example
700
+
701
+ ```
702
+ ╭──────────────────────────────────────────────────────────────────────────────╮
703
+ │ 👥 გუნდის წევრები │
704
+ ├──────────────────────────────────────────────────────────────────────────────┤
705
+ │ │
706
+ │ 📁 პროექტი: Planflow Plugin │
707
+ │ │
708
+ │ ── აქტიური წევრები (3) ───────────────────────────────────────────────── │
709
+ │ │
710
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
711
+ │ │ 🟢 John Doe (მფლობელი) │ │
712
+ │ │ john@company.com │ │
713
+ │ │ მუშაობს: T2.1 - API endpoints │ │
714
+ │ └────────────────────────────────────────────────────────────────────────┘ │
715
+ │ │
716
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
717
+ │ │ 🟢 Jane Smith (ადმინი) │ │
718
+ │ │ jane@company.com │ │
719
+ │ │ მუშაობს: T3.5 - Dashboard │ │
720
+ │ └────────────────────────────────────────────────────────────────────────┘ │
721
+ │ │
722
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
723
+ │ │ 🔴 Bob Wilson (რედაქტორი) │ │
724
+ │ │ bob@company.com │ │
725
+ │ │ ბოლოს ნანახი: 2 საათის წინ │ │
726
+ │ └────────────────────────────────────────────────────────────────────────┘ │
727
+ │ │
728
+ │ ── მოლოდინში მყოფი მოწვევები (1) ─────────────────────────────────────── │
729
+ │ │
730
+ │ ⏳ alice@company.com (რედაქტორი) - გაგზავნილი 2 დღის წინ │
731
+ │ │
732
+ ├──────────────────────────────────────────────────────────────────────────────┤
733
+ │ │
734
+ │ 💡 ბრძანებები: │
735
+ │ • /team add <email> მოიწვიე გუნდის წევრი │
736
+ │ • /team role <email> <role> შეცვალე წევრის როლი │
737
+ │ │
738
+ ╰──────────────────────────────────────────────────────────────────────────────╯
739
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
740
+ ```