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,623 @@
1
+ ---
2
+ name: pfAssign
3
+ description: Assign a task to a team member in the current PlanFlow project
4
+ ---
5
+
6
+ # PlanFlow Task Assignment
7
+
8
+ Assign a task to a team member or yourself in the linked cloud project.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ /pfAssign <task-id> <email|me> # Assign task to team member or self
14
+ /pfAssign T2.1 jane@company.com # Assign to specific member
15
+ /pfAssign T2.1 me # Assign to yourself
16
+ ```
17
+
18
+ ## Process
19
+
20
+ ### Step 0: Load User Language & Translations
21
+
22
+ **CRITICAL: Execute this step FIRST, before any output!**
23
+
24
+ Load user's language preference using hierarchical config (local → global → default) and translation file.
25
+
26
+ **Pseudo-code:**
27
+ ```javascript
28
+ // Read config with hierarchy AND MERGE
29
+ function getMergedConfig() {
30
+ let globalConfig = {}
31
+ let localConfig = {}
32
+
33
+ // Read global config first (base)
34
+ const globalPath = expandPath("~/.config/claude/plan-plugin-config.json")
35
+ if (fileExists(globalPath)) {
36
+ try {
37
+ globalConfig = JSON.parse(readFile(globalPath))
38
+ } catch (error) {}
39
+ }
40
+
41
+ // Read local config (overrides)
42
+ if (fileExists("./.plan-config.json")) {
43
+ try {
44
+ localConfig = JSON.parse(readFile("./.plan-config.json"))
45
+ } catch (error) {}
46
+ }
47
+
48
+ // Merge configs: local overrides global, but cloud settings are merged
49
+ const mergedConfig = {
50
+ ...globalConfig,
51
+ ...localConfig,
52
+ cloud: {
53
+ ...(globalConfig.cloud || {}),
54
+ ...(localConfig.cloud || {})
55
+ }
56
+ }
57
+
58
+ return mergedConfig
59
+ }
60
+
61
+ const config = getMergedConfig()
62
+ const language = config.language || "en"
63
+
64
+ // Cloud config - properly merged from both configs
65
+ const cloudConfig = config.cloud || {}
66
+ const isAuthenticated = !!cloudConfig.apiToken
67
+ const apiUrl = cloudConfig.apiUrl || "https://api.planflow.tools"
68
+ const projectId = cloudConfig.projectId || null
69
+ const currentUserEmail = cloudConfig.userEmail || null
70
+
71
+ // Load translations
72
+ const translationPath = `locales/${language}.json`
73
+ const t = JSON.parse(readFile(translationPath))
74
+ ```
75
+
76
+ **Instructions for Claude:**
77
+
78
+ 1. Read BOTH config files and MERGE them:
79
+ - First read `~/.config/claude/plan-plugin-config.json` (global, base)
80
+ - Then read `./.plan-config.json` (local, overrides)
81
+ - Merge the `cloud` sections: global values + local overrides
82
+ 2. Use Read tool: `locales/{language}.json`
83
+ 3. Store as `t` variable
84
+
85
+ ---
86
+
87
+ ### Step 1: Show Usage Card (if no arguments)
88
+
89
+ If no arguments provided, display usage information.
90
+
91
+ **Output:**
92
+
93
+ ```
94
+ ╭──────────────────────────────────────────────────────────────────────────────╮
95
+ │ 📋 Task Assignment │
96
+ ├──────────────────────────────────────────────────────────────────────────────┤
97
+ │ │
98
+ │ ── Usage ─────────────────────────────────────────────────────────────── │
99
+ │ │
100
+ │ /pfAssign <task-id> <email> Assign to team member by email │
101
+ │ /pfAssign <task-id> me Assign to yourself │
102
+ │ │
103
+ │ ── Examples ──────────────────────────────────────────────────────────── │
104
+ │ │
105
+ │ /pfAssign T2.1 jane@company.com │
106
+ │ /pfAssign T2.1 me │
107
+ │ │
108
+ ╰──────────────────────────────────────────────────────────────────────────────╯
109
+ ```
110
+
111
+ **Instructions for Claude:**
112
+
113
+ Use translation keys:
114
+ - `t.commands.assign.title`
115
+ - `t.commands.assign.usage`
116
+ - `t.commands.assign.usageEmail`
117
+ - `t.commands.assign.usageMe`
118
+ - `t.commands.assign.example`
119
+
120
+ ---
121
+
122
+ ### Step 2: Check Prerequisites
123
+
124
+ Verify user is authenticated and project is linked.
125
+
126
+ **Pseudo-code:**
127
+ ```javascript
128
+ if (!isAuthenticated) {
129
+ showError(t.commands.sync.notAuthenticated)
130
+ // "❌ Not authenticated. Run /pfLogin first."
131
+ return
132
+ }
133
+
134
+ if (!projectId) {
135
+ showError(t.commands.sync.notLinked)
136
+ // "❌ Project not linked to cloud. Run /pfCloudLink first."
137
+ return
138
+ }
139
+ ```
140
+
141
+ **Not Authenticated Card:**
142
+
143
+ ```
144
+ ╭──────────────────────────────────────────────────────────────────────────────╮
145
+ │ ❌ ERROR │
146
+ ├──────────────────────────────────────────────────────────────────────────────┤
147
+ │ │
148
+ │ Not authenticated. │
149
+ │ │
150
+ │ 💡 Run /pfLogin first to authenticate. │
151
+ │ │
152
+ ╰──────────────────────────────────────────────────────────────────────────────╯
153
+ ```
154
+
155
+ **Not Linked Card:**
156
+
157
+ ```
158
+ ╭──────────────────────────────────────────────────────────────────────────────╮
159
+ │ ❌ ERROR │
160
+ ├──────────────────────────────────────────────────────────────────────────────┤
161
+ │ │
162
+ │ Project not linked to cloud. │
163
+ │ │
164
+ │ 💡 Run /pfCloudLink first to link a project. │
165
+ │ │
166
+ ╰──────────────────────────────────────────────────────────────────────────────╯
167
+ ```
168
+
169
+ ---
170
+
171
+ ### Step 3: Parse and Validate Arguments
172
+
173
+ Parse the task ID and assignee from arguments.
174
+
175
+ **Pseudo-code:**
176
+ ```javascript
177
+ // Parse arguments: /pfAssign T2.1 jane@company.com
178
+ const args = parseArguments(input) // ["T2.1", "jane@company.com"]
179
+ const taskId = args[0] // "T2.1"
180
+ const assigneeArg = args[1] // "jane@company.com" or "me"
181
+
182
+ // Validate task ID format (T followed by numbers and dots)
183
+ const taskIdRegex = /^T\d+\.\d+$/i
184
+ if (!taskId || !taskIdRegex.test(taskId)) {
185
+ showError(t.commands.assign.invalidTaskId)
186
+ showHint(t.commands.assign.taskIdExample)
187
+ return
188
+ }
189
+
190
+ // Normalize task ID to uppercase
191
+ const normalizedTaskId = taskId.toUpperCase()
192
+
193
+ // Check assignee argument
194
+ if (!assigneeArg) {
195
+ showError("Missing assignee. Provide an email or 'me'.")
196
+ return
197
+ }
198
+
199
+ // Determine assignee email
200
+ let assigneeEmail
201
+ if (assigneeArg.toLowerCase() === "me") {
202
+ assigneeEmail = currentUserEmail
203
+ isSelfAssignment = true
204
+ } else {
205
+ // Validate email format
206
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
207
+ if (!emailRegex.test(assigneeArg)) {
208
+ showError(t.commands.assign.invalidEmail)
209
+ showHint(t.commands.assign.emailExample)
210
+ return
211
+ }
212
+ assigneeEmail = assigneeArg.toLowerCase()
213
+ isSelfAssignment = (assigneeEmail === currentUserEmail)
214
+ }
215
+ ```
216
+
217
+ **Invalid Task ID Card:**
218
+
219
+ ```
220
+ ╭──────────────────────────────────────────────────────────────────────────────╮
221
+ │ ❌ ERROR │
222
+ ├──────────────────────────────────────────────────────────────────────────────┤
223
+ │ │
224
+ │ Invalid task ID format. │
225
+ │ │
226
+ │ Task ID should be like: T1.1, T2.3, T10.5 │
227
+ │ │
228
+ ╰──────────────────────────────────────────────────────────────────────────────╯
229
+ ```
230
+
231
+ **Invalid Email Card:**
232
+
233
+ ```
234
+ ╭──────────────────────────────────────────────────────────────────────────────╮
235
+ │ ❌ ERROR │
236
+ ├──────────────────────────────────────────────────────────────────────────────┤
237
+ │ │
238
+ │ Invalid email format. │
239
+ │ │
240
+ │ Example: jane@company.com or use 'me' │
241
+ │ │
242
+ ╰──────────────────────────────────────────────────────────────────────────────╯
243
+ ```
244
+
245
+ ---
246
+
247
+ ### Step 4: Make API Request to Assign Task
248
+
249
+ Call the PlanFlow API to assign the task.
250
+
251
+ **API Endpoint:**
252
+ ```
253
+ POST /projects/{projectId}/tasks/{taskId}/assign
254
+ ```
255
+
256
+ **Request Body:**
257
+ ```json
258
+ {
259
+ "email": "jane@company.com"
260
+ }
261
+ ```
262
+
263
+ **Bash Implementation:**
264
+
265
+ ```bash
266
+ API_URL="https://api.planflow.tools"
267
+ TOKEN="$API_TOKEN"
268
+ PROJECT_ID="$PROJECT_ID"
269
+ TASK_ID="T2.1"
270
+ ASSIGNEE_EMAIL="jane@company.com"
271
+
272
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
273
+ --connect-timeout 5 \
274
+ --max-time 10 \
275
+ -X POST \
276
+ -H "Content-Type: application/json" \
277
+ -H "Accept: application/json" \
278
+ -H "Authorization: Bearer $TOKEN" \
279
+ -d "{\"email\": \"$ASSIGNEE_EMAIL\"}" \
280
+ "${API_URL}/projects/${PROJECT_ID}/tasks/${TASK_ID}/assign")
281
+
282
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
283
+ BODY=$(echo "$RESPONSE" | sed '$d')
284
+
285
+ echo "HTTP Code: $HTTP_CODE"
286
+ echo "Body: $BODY"
287
+ ```
288
+
289
+ **Instructions for Claude:**
290
+
291
+ 1. Make POST request to `/projects/{projectId}/tasks/{taskId}/assign`
292
+ 2. Include `{"email": "{assigneeEmail}"}` in body
293
+ 3. Parse response to get task and assignee details
294
+
295
+ ---
296
+
297
+ ### Step 5: Handle Response
298
+
299
+ Process the API response and display appropriate card.
300
+
301
+ **Success Response (200):**
302
+ ```json
303
+ {
304
+ "success": true,
305
+ "data": {
306
+ "task": {
307
+ "taskId": "T2.1",
308
+ "name": "Implement login API",
309
+ "status": "TODO",
310
+ "assignee": {
311
+ "id": "uuid",
312
+ "email": "jane@company.com",
313
+ "name": "Jane Smith"
314
+ }
315
+ },
316
+ "project": {
317
+ "id": "uuid",
318
+ "name": "Planflow Plugin"
319
+ }
320
+ }
321
+ }
322
+ ```
323
+
324
+ **Pseudo-code for Response Handling:**
325
+ ```javascript
326
+ if (httpCode >= 200 && httpCode < 300) {
327
+ const data = JSON.parse(body).data
328
+ const task = data.task
329
+ const project = data.project
330
+ const assignee = task.assignee
331
+
332
+ if (isSelfAssignment) {
333
+ showSelfAssignmentSuccessCard(task, project, currentUserEmail)
334
+ } else {
335
+ showAssignmentSuccessCard(task, project, assignee)
336
+ }
337
+ } else if (httpCode === 404) {
338
+ // Task not found
339
+ showTaskNotFoundCard(taskId)
340
+ } else if (httpCode === 409) {
341
+ // Task already assigned or user not a member
342
+ const error = JSON.parse(body).error
343
+ if (error.code === "ALREADY_ASSIGNED") {
344
+ showAlreadyAssignedCard(taskId, error.currentAssignee)
345
+ } else if (error.code === "USER_NOT_MEMBER") {
346
+ showUserNotMemberCard(assigneeEmail)
347
+ }
348
+ } else if (httpCode === 403) {
349
+ // Permission denied
350
+ showPermissionDeniedCard()
351
+ } else {
352
+ // Other error
353
+ showGenericErrorCard()
354
+ }
355
+ ```
356
+
357
+ ---
358
+
359
+ ### Step 6: Display Success Card
360
+
361
+ **Assignment Success Card (to other team member):**
362
+
363
+ ```
364
+ ╭──────────────────────────────────────────────────────────────────────────────╮
365
+ │ ✅ SUCCESS │
366
+ ├──────────────────────────────────────────────────────────────────────────────┤
367
+ │ │
368
+ │ Task assigned! │
369
+ │ │
370
+ │ ── Assignment Details ────────────────────────────────────────────────── │
371
+ │ │
372
+ │ 📋 Task: T2.1: Implement login API │
373
+ │ 👤 Assigned to: Jane Smith (jane@company.com) │
374
+ │ 📁 Project: Planflow Plugin │
375
+ │ │
376
+ │ ╭───────────────────╮ │
377
+ │ │ ✓ Assigned │ │
378
+ │ ╰───────────────────╯ │
379
+ │ │
380
+ │ They'll be notified of this assignment. │
381
+ │ │
382
+ ├──────────────────────────────────────────────────────────────────────────────┤
383
+ │ │
384
+ │ 💡 Commands: │
385
+ │ • /pfUnassign T2.1 Remove assignment │
386
+ │ • /pfWorkload View team workload │
387
+ │ │
388
+ ╰──────────────────────────────────────────────────────────────────────────────╯
389
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
390
+ ```
391
+
392
+ **Self-Assignment Success Card:**
393
+
394
+ ```
395
+ ╭──────────────────────────────────────────────────────────────────────────────╮
396
+ │ ✅ SUCCESS │
397
+ ├──────────────────────────────────────────────────────────────────────────────┤
398
+ │ │
399
+ │ Task assigned to you! │
400
+ │ │
401
+ │ ── Assignment Details ────────────────────────────────────────────────── │
402
+ │ │
403
+ │ 📋 Task: T2.1: Implement login API │
404
+ │ 👤 Assigned to: You (john@company.com) │
405
+ │ 📁 Project: Planflow Plugin │
406
+ │ │
407
+ │ ╭───────────────────╮ │
408
+ │ │ ✓ Assigned │ │
409
+ │ ╰───────────────────╯ │
410
+ │ │
411
+ ├──────────────────────────────────────────────────────────────────────────────┤
412
+ │ │
413
+ │ 💡 Ready to start working? │
414
+ │ • /planUpdate T2.1 start │
415
+ │ │
416
+ ╰──────────────────────────────────────────────────────────────────────────────╯
417
+ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
418
+ ```
419
+
420
+ **Instructions for Claude:**
421
+
422
+ Use translation keys:
423
+ - `t.commands.assign.success` - "Task assigned!"
424
+ - `t.commands.assign.task` - "Task:"
425
+ - `t.commands.assign.assignedTo` - "Assigned to:"
426
+ - `t.commands.assign.project` - "Project:"
427
+ - `t.commands.assign.notifyHint` - "They'll be notified of this assignment."
428
+ - `t.commands.assign.selfAssignHint` - "Ready to start working? Run:"
429
+
430
+ ---
431
+
432
+ ## Error Handling
433
+
434
+ ### Task Not Found Card (404)
435
+
436
+ ```
437
+ ╭──────────────────────────────────────────────────────────────────────────────╮
438
+ │ ❌ ERROR │
439
+ ├──────────────────────────────────────────────────────────────────────────────┤
440
+ │ │
441
+ │ Task not found: T2.1 │
442
+ │ │
443
+ │ Make sure the task exists in the cloud project. │
444
+ │ │
445
+ │ 💡 Run /pfSyncPush to sync your local tasks first. │
446
+ │ │
447
+ ╰──────────────────────────────────────────────────────────────────────────────╯
448
+ ```
449
+
450
+ **Translation keys:**
451
+ - `t.commands.assign.taskNotFound`
452
+ - `t.commands.assign.checkTaskId`
453
+
454
+ ---
455
+
456
+ ### User Not Team Member Card (409 - USER_NOT_MEMBER)
457
+
458
+ ```
459
+ ╭──────────────────────────────────────────────────────────────────────────────╮
460
+ │ ❌ ERROR │
461
+ ├──────────────────────────────────────────────────────────────────────────────┤
462
+ │ │
463
+ │ User is not a team member. │
464
+ │ │
465
+ │ jane@company.com is not part of this project. │
466
+ │ │
467
+ │ 💡 Invite them first: │
468
+ │ • /pfTeamInvite jane@company.com │
469
+ │ │
470
+ ╰──────────────────────────────────────────────────────────────────────────────╯
471
+ ```
472
+
473
+ **Translation keys:**
474
+ - `t.commands.assign.userNotMember`
475
+ - `t.commands.assign.notMemberHint`
476
+ - `t.commands.assign.inviteFirst`
477
+
478
+ ---
479
+
480
+ ### Task Already Assigned Card (409 - ALREADY_ASSIGNED)
481
+
482
+ ```
483
+ ╭──────────────────────────────────────────────────────────────────────────────╮
484
+ │ ⚠️ WARNING │
485
+ ├──────────────────────────────────────────────────────────────────────────────┤
486
+ │ │
487
+ │ Task is already assigned. │
488
+ │ │
489
+ │ T2.1 is currently assigned to Bob Wilson (bob@company.com) │
490
+ │ │
491
+ │ 💡 To reassign: │
492
+ │ • /pfUnassign T2.1 │
493
+ │ • /pfAssign T2.1 jane@company.com │
494
+ │ │
495
+ ╰──────────────────────────────────────────────────────────────────────────────╯
496
+ ```
497
+
498
+ **Translation keys:**
499
+ - `t.commands.assign.alreadyAssigned`
500
+ - `t.commands.assign.reassignHint`
501
+
502
+ ---
503
+
504
+ ### Permission Denied Card (403)
505
+
506
+ ```
507
+ ╭──────────────────────────────────────────────────────────────────────────────╮
508
+ │ ❌ ERROR │
509
+ ├──────────────────────────────────────────────────────────────────────────────┤
510
+ │ │
511
+ │ You don't have permission to assign tasks. │
512
+ │ │
513
+ │ Only editors and above can assign tasks. │
514
+ │ │
515
+ ╰──────────────────────────────────────────────────────────────────────────────╯
516
+ ```
517
+
518
+ **Translation keys:**
519
+ - `t.commands.assign.noPermission`
520
+ - `t.commands.assign.noPermissionHint`
521
+
522
+ ---
523
+
524
+ ### Network Error Card
525
+
526
+ ```
527
+ ╭──────────────────────────────────────────────────────────────────────────────╮
528
+ │ ❌ ERROR │
529
+ ├──────────────────────────────────────────────────────────────────────────────┤
530
+ │ │
531
+ │ Could not connect to PlanFlow. │
532
+ │ │
533
+ │ Please check your connection and try again. │
534
+ │ │
535
+ ╰──────────────────────────────────────────────────────────────────────────────╯
536
+ ```
537
+
538
+ **Translation keys:**
539
+ - `t.commands.assign.tryAgain`
540
+
541
+ ---
542
+
543
+ ## Complete Flow Diagram
544
+
545
+ ```
546
+ /pfAssign T2.1 jane@company.com
547
+
548
+
549
+ ┌─────────────────────────────────────┐
550
+ │ Step 0: Load config & translations │
551
+ └──────────────┬──────────────────────┘
552
+
553
+
554
+ ┌─────────────────────────────────────┐
555
+ │ Step 1: Check if args provided │
556
+ │ No args → Show usage card │
557
+ └──────────────┬──────────────────────┘
558
+ │ Has args
559
+
560
+ ┌─────────────────────────────────────┐
561
+ │ Step 2: Check prerequisites │
562
+ │ - Authenticated? │
563
+ │ - Project linked? │
564
+ └──────────────┬──────────────────────┘
565
+ │ Yes
566
+
567
+ ┌─────────────────────────────────────┐
568
+ │ Step 3: Validate arguments │
569
+ │ - Task ID format │
570
+ │ - Email format or "me" │
571
+ └──────────────┬──────────────────────┘
572
+ │ Valid
573
+
574
+ ┌─────────────────────────────────────┐
575
+ │ Step 4: Make API request │
576
+ │ POST /tasks/{id}/assign │
577
+ └──────────────┬──────────────────────┘
578
+
579
+
580
+ ┌─────────────────────────────────────┐
581
+ │ Step 5: Handle response │
582
+ │ - 200 → Success card │
583
+ │ - 404 → Task not found │
584
+ │ - 409 → Already assigned │
585
+ │ - 403 → Permission denied │
586
+ └─────────────────────────────────────┘
587
+ ```
588
+
589
+ ---
590
+
591
+ ## Georgian Translations Reference
592
+
593
+ For Georgian output, use keys from `locales/ka.json`:
594
+
595
+ ```
596
+ 📋 ამოცანის მინიჭება
597
+
598
+ გამოყენება:
599
+ /pfAssign <task-id> <email> მინიჭება გუნდის წევრზე ელფოსტით
600
+ /pfAssign <task-id> me მინიჭება საკუთარ თავზე
601
+
602
+ მაგალითები:
603
+ /pfAssign T2.1 jane@company.com
604
+ /pfAssign T2.1 me
605
+ ```
606
+
607
+ ---
608
+
609
+ ## Success Criteria
610
+
611
+ A successful implementation should:
612
+ - ✅ Load merged config (global + local)
613
+ - ✅ Load appropriate language translations
614
+ - ✅ Show usage card when no arguments
615
+ - ✅ Validate authentication and project link
616
+ - ✅ Validate task ID format (T1.1, T2.3, etc.)
617
+ - ✅ Validate email format or accept "me"
618
+ - ✅ Handle "me" → current user's email
619
+ - ✅ Make POST request to assign endpoint
620
+ - ✅ Show success card with task and assignee details
621
+ - ✅ Show different card for self-assignment
622
+ - ✅ Handle all error cases with appropriate cards
623
+ - ✅ Use translation keys for all user-facing text