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,725 @@
1
+ ---
2
+ name: pfActivity
3
+ description: View recent activity in the current PlanFlow project
4
+ ---
5
+
6
+ # PlanFlow Activity Feed
7
+
8
+ View recent activity in the linked cloud project with activity feed cards.
9
+
10
+ ## Usage
11
+
12
+ ```bash
13
+ /pfActivity # Show recent project activity
14
+ /pfActivity T2.1 # Show activity for specific task
15
+ /pfActivity --limit 20 # Show more entries (default: 10)
16
+ /pfActivity --type tasks # Filter by activity type
17
+ ```
18
+
19
+ ## Process
20
+
21
+ ### Step 0: Load User Language & Translations
22
+
23
+ **CRITICAL: Execute this step FIRST, before any output!**
24
+
25
+ Load user's language preference using hierarchical config (local → global → default) and translation file.
26
+
27
+ **Pseudo-code:**
28
+ ```javascript
29
+ // Read config with hierarchy AND MERGE
30
+ function getMergedConfig() {
31
+ let globalConfig = {}
32
+ let localConfig = {}
33
+
34
+ // Read global config first (base)
35
+ const globalPath = expandPath("~/.config/claude/plan-plugin-config.json")
36
+ if (fileExists(globalPath)) {
37
+ try {
38
+ globalConfig = JSON.parse(readFile(globalPath))
39
+ } catch (error) {}
40
+ }
41
+
42
+ // Read local config (overrides)
43
+ if (fileExists("./.plan-config.json")) {
44
+ try {
45
+ localConfig = JSON.parse(readFile("./.plan-config.json"))
46
+ } catch (error) {}
47
+ }
48
+
49
+ // Merge configs: local overrides global, but cloud settings are merged
50
+ const mergedConfig = {
51
+ ...globalConfig,
52
+ ...localConfig,
53
+ cloud: {
54
+ ...(globalConfig.cloud || {}),
55
+ ...(localConfig.cloud || {})
56
+ }
57
+ }
58
+
59
+ return mergedConfig
60
+ }
61
+
62
+ const config = getMergedConfig()
63
+ const language = config.language || "en"
64
+
65
+ // Cloud config - properly merged from both configs
66
+ const cloudConfig = config.cloud || {}
67
+ const isAuthenticated = !!cloudConfig.apiToken
68
+ const apiUrl = cloudConfig.apiUrl || "https://api.planflow.tools"
69
+ const projectId = cloudConfig.projectId || null
70
+ const projectName = cloudConfig.projectName || "Unknown Project"
71
+
72
+ // Load translations
73
+ const translationPath = `locales/${language}.json`
74
+ const t = JSON.parse(readFile(translationPath))
75
+ ```
76
+
77
+ **Instructions for Claude:**
78
+
79
+ 1. Read BOTH config files and MERGE them:
80
+ - First read `~/.config/claude/plan-plugin-config.json` (global, base)
81
+ - Then read `./.plan-config.json` (local, overrides)
82
+ - Merge the `cloud` sections: global values + local overrides
83
+ 2. Use Read tool: `locales/{language}.json`
84
+ 3. Store as `t` variable
85
+
86
+ ---
87
+
88
+ ### Step 1: Parse Arguments
89
+
90
+ Parse the command arguments to extract task ID, limit, and type filter.
91
+
92
+ **Pseudo-code:**
93
+ ```javascript
94
+ function parseArgs(args) {
95
+ let taskId = null
96
+ let limit = 10
97
+ let activityType = null
98
+
99
+ const parts = args.trim().split(/\s+/)
100
+
101
+ for (let i = 0; i < parts.length; i++) {
102
+ const part = parts[i]
103
+
104
+ if (part === '--limit' && parts[i + 1]) {
105
+ limit = parseInt(parts[i + 1], 10)
106
+ if (isNaN(limit) || limit < 1) limit = 10
107
+ if (limit > 50) limit = 50
108
+ i++ // Skip next part
109
+ } else if (part === '--type' && parts[i + 1]) {
110
+ activityType = parts[i + 1]
111
+ i++ // Skip next part
112
+ } else if (part.match(/^T\d+\.\d+$/i)) {
113
+ taskId = part.toUpperCase()
114
+ } else if (part === '--help' || part === '-h') {
115
+ return { showHelp: true }
116
+ }
117
+ }
118
+
119
+ return { taskId, limit, activityType, showHelp: false }
120
+ }
121
+
122
+ const { taskId, limit, activityType, showHelp } = parseArgs(ARGUMENTS)
123
+ ```
124
+
125
+ **Activity Type Mapping:**
126
+ - `tasks` → action filter: `task_status_changed`
127
+ - `comments` → action filter: `comment_created`
128
+ - `assignments` → action filter: `task_assigned`
129
+ - `team` → entity filter: `member`
130
+
131
+ ---
132
+
133
+ ### Step 2: Show Usage Card (if help requested or no project linked)
134
+
135
+ If `--help` is provided or no project is linked, display usage information.
136
+
137
+ **Output:**
138
+
139
+ ```
140
+ ╭──────────────────────────────────────────────────────────────────────────────╮
141
+ │ 📊 Activity Feed │
142
+ ├──────────────────────────────────────────────────────────────────────────────┤
143
+ │ │
144
+ │ ── Usage ─────────────────────────────────────────────────────────────── │
145
+ │ │
146
+ │ /pfActivity Show recent project activity │
147
+ │ /pfActivity <task-id> Show activity for specific task │
148
+ │ /pfActivity --limit <n> Show more entries (default: 10, max: 50) │
149
+ │ /pfActivity --type <type> Filter by activity type │
150
+ │ │
151
+ │ ── Activity Types ───────────────────────────────────────────────────── │
152
+ │ │
153
+ │ tasks - Task status changes │
154
+ │ comments - Comment activity │
155
+ │ assignments - Task assignments │
156
+ │ team - Team membership changes │
157
+ │ │
158
+ │ ── Examples ──────────────────────────────────────────────────────────── │
159
+ │ │
160
+ │ /pfActivity T2.1 │
161
+ │ /pfActivity --type comments --limit 20 │
162
+ │ │
163
+ ╰──────────────────────────────────────────────────────────────────────────────╯
164
+ ```
165
+
166
+ ---
167
+
168
+ ### Step 3: Check Prerequisites
169
+
170
+ Verify user is authenticated and project is linked.
171
+
172
+ **Pseudo-code:**
173
+ ```javascript
174
+ if (!isAuthenticated) {
175
+ showError(t.commands.sync.notAuthenticated)
176
+ // "❌ Not authenticated. Run /pfLogin first."
177
+ return
178
+ }
179
+
180
+ if (!projectId) {
181
+ showError(t.commands.sync.notLinked)
182
+ // "❌ Project not linked to cloud. Run /pfCloudLink first."
183
+ return
184
+ }
185
+ ```
186
+
187
+ **Not Authenticated Card:**
188
+
189
+ ```
190
+ ╭──────────────────────────────────────────────────────────────────────────────╮
191
+ │ ❌ ERROR │
192
+ ├──────────────────────────────────────────────────────────────────────────────┤
193
+ │ │
194
+ │ Not authenticated. │
195
+ │ │
196
+ │ 💡 Run /pfLogin first to authenticate. │
197
+ │ │
198
+ ╰──────────────────────────────────────────────────────────────────────────────╯
199
+ ```
200
+
201
+ **Not Linked Card:**
202
+
203
+ ```
204
+ ╭──────────────────────────────────────────────────────────────────────────────╮
205
+ │ ❌ ERROR │
206
+ ├──────────────────────────────────────────────────────────────────────────────┤
207
+ │ │
208
+ │ Project not linked to cloud. │
209
+ │ │
210
+ │ 💡 Run /pfCloudLink first to link this project. │
211
+ │ │
212
+ ╰──────────────────────────────────────────────────────────────────────────────╯
213
+ ```
214
+
215
+ ---
216
+
217
+ ### Step 4: Fetch Activity from API
218
+
219
+ Make API request to fetch activity.
220
+
221
+ **Pseudo-code:**
222
+ ```javascript
223
+ async function fetchActivity(projectId, taskId, limit, activityType, apiToken, apiUrl) {
224
+ let endpoint
225
+ const params = new URLSearchParams()
226
+ params.append('limit', String(limit))
227
+
228
+ if (taskId) {
229
+ // Task-specific activity
230
+ endpoint = `${apiUrl}/projects/${projectId}/tasks/${taskId}/activity`
231
+ } else {
232
+ // Project activity
233
+ endpoint = `${apiUrl}/projects/${projectId}/activity`
234
+ }
235
+
236
+ // Add type filter
237
+ if (activityType) {
238
+ switch (activityType) {
239
+ case 'tasks':
240
+ params.append('action', 'task_status_changed')
241
+ break
242
+ case 'comments':
243
+ params.append('action', 'comment_created')
244
+ break
245
+ case 'assignments':
246
+ params.append('action', 'task_assigned')
247
+ break
248
+ case 'team':
249
+ params.append('entityType', 'member')
250
+ break
251
+ }
252
+ }
253
+
254
+ const url = `${endpoint}?${params.toString()}`
255
+
256
+ const response = await fetch(url, {
257
+ method: 'GET',
258
+ headers: {
259
+ 'Authorization': `Bearer ${apiToken}`,
260
+ 'Accept': 'application/json'
261
+ }
262
+ })
263
+
264
+ if (!response.ok) {
265
+ throw new Error(`HTTP ${response.status}`)
266
+ }
267
+
268
+ return response.json()
269
+ }
270
+ ```
271
+
272
+ **Bash Implementation:**
273
+
274
+ ```bash
275
+ API_URL="https://api.planflow.tools"
276
+ TOKEN="$API_TOKEN"
277
+ PROJECT_ID="$PROJECT_ID"
278
+ TASK_ID="$TASK_ID" # Optional
279
+ LIMIT="10"
280
+
281
+ # Build URL
282
+ if [ -n "$TASK_ID" ]; then
283
+ ENDPOINT="${API_URL}/projects/${PROJECT_ID}/tasks/${TASK_ID}/activity"
284
+ else
285
+ ENDPOINT="${API_URL}/projects/${PROJECT_ID}/activity"
286
+ fi
287
+
288
+ # Make request
289
+ RESPONSE=$(curl -s -w "\n%{http_code}" \
290
+ --connect-timeout 5 \
291
+ --max-time 15 \
292
+ -X GET \
293
+ -H "Accept: application/json" \
294
+ -H "Authorization: Bearer $TOKEN" \
295
+ "${ENDPOINT}?limit=${LIMIT}")
296
+
297
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
298
+ BODY=$(echo "$RESPONSE" | sed '$d')
299
+
300
+ if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
301
+ echo "$BODY"
302
+ else
303
+ echo "Error: HTTP $HTTP_CODE"
304
+ fi
305
+ ```
306
+
307
+ **Instructions for Claude:**
308
+
309
+ 1. Build the API URL based on whether taskId is provided
310
+ 2. Add query parameters for limit and type filters
311
+ 3. Make GET request with authorization header
312
+ 4. Parse JSON response
313
+
314
+ ---
315
+
316
+ ### Step 5: Format Activity Items
317
+
318
+ Format each activity item for display.
319
+
320
+ **Activity Icons:**
321
+
322
+ | Action | Icon |
323
+ |--------|------|
324
+ | task_created | ✨ |
325
+ | task_updated | 📝 |
326
+ | task_status_changed | 🔄 |
327
+ | task_assigned | 👤 |
328
+ | task_unassigned | 👤 |
329
+ | comment_created | 💬 |
330
+ | comment_updated | ✏️ |
331
+ | comment_deleted | 🗑️ |
332
+ | project_updated | 📋 |
333
+ | plan_updated | 📄 |
334
+ | member_invited | 📨 |
335
+ | member_joined | 🎉 |
336
+ | member_removed | 👋 |
337
+ | member_role_changed | 🔑 |
338
+
339
+ **Status Icons for task_status_changed:**
340
+
341
+ | New Status | Icon |
342
+ |------------|------|
343
+ | DONE | ✅ |
344
+ | IN_PROGRESS | 🔄 |
345
+ | BLOCKED | 🚫 |
346
+ | TODO | ⬜ |
347
+
348
+ **Relative Time Formatting:**
349
+
350
+ ```javascript
351
+ function formatRelativeTime(dateString) {
352
+ const date = new Date(dateString)
353
+ const now = new Date()
354
+ const diffMs = now.getTime() - date.getTime()
355
+ const diffMinutes = Math.floor(diffMs / 60000)
356
+ const diffHours = Math.floor(diffMinutes / 60)
357
+ const diffDays = Math.floor(diffHours / 24)
358
+
359
+ if (diffMinutes < 1) return 'just now'
360
+ if (diffMinutes < 60) return `${diffMinutes} min ago`
361
+ if (diffHours < 24) return `${diffHours}h ago`
362
+ if (diffDays < 7) return `${diffDays}d ago`
363
+ return date.toLocaleDateString()
364
+ }
365
+ ```
366
+
367
+ **Activity Message Formatting:**
368
+
369
+ ```javascript
370
+ function formatActivityMessage(activity) {
371
+ const actor = activity.actor.name || activity.actor.email.split('@')[0]
372
+ const taskId = activity.taskId
373
+
374
+ switch (activity.action) {
375
+ case 'task_status_changed':
376
+ const newStatus = activity.metadata?.newStatus
377
+ const statusIcon = getStatusIcon(newStatus)
378
+ if (taskId) {
379
+ return `${statusIcon} ${actor} marked ${taskId} as ${newStatus.toLowerCase()}`
380
+ }
381
+ return `${statusIcon} ${actor} changed task status to ${newStatus.toLowerCase()}`
382
+
383
+ case 'task_assigned':
384
+ const assignee = activity.metadata?.assigneeName || activity.metadata?.assigneeEmail
385
+ if (taskId) {
386
+ return `👤 ${actor} assigned ${taskId} to ${assignee}`
387
+ }
388
+ return `👤 ${actor} assigned task to ${assignee}`
389
+
390
+ case 'task_unassigned':
391
+ if (taskId) {
392
+ return `👤 ${actor} unassigned ${taskId}`
393
+ }
394
+ return `👤 ${actor} removed assignment`
395
+
396
+ case 'comment_created':
397
+ const preview = activity.metadata?.commentPreview
398
+ if (taskId && preview) {
399
+ return `💬 ${actor} commented on ${taskId}\n "${truncate(preview, 40)}"`
400
+ }
401
+ if (taskId) {
402
+ return `💬 ${actor} commented on ${taskId}`
403
+ }
404
+ return `💬 ${actor} added a comment`
405
+
406
+ case 'member_joined':
407
+ return `🎉 ${actor} joined the project`
408
+
409
+ case 'member_invited':
410
+ const invitee = activity.metadata?.inviteeEmail
411
+ return `📨 ${actor} invited ${invitee}`
412
+
413
+ case 'member_removed':
414
+ return `👋 ${actor} left the project`
415
+
416
+ case 'member_role_changed':
417
+ const newRole = activity.metadata?.newRole
418
+ return `🔑 ${actor}'s role changed to ${newRole}`
419
+
420
+ case 'plan_updated':
421
+ return `📄 ${actor} updated the project plan`
422
+
423
+ default:
424
+ return `📌 ${actor} ${activity.description || activity.action.replace(/_/g, ' ')}`
425
+ }
426
+ }
427
+ ```
428
+
429
+ ---
430
+
431
+ ### Step 6: Display Activity Feed Card
432
+
433
+ Display the activity feed in a formatted card.
434
+
435
+ **Project Activity Card:**
436
+
437
+ ```
438
+ ╭──────────────────────────────────────────────────────────────────────────────╮
439
+ │ 📊 Recent Activity │
440
+ ├──────────────────────────────────────────────────────────────────────────────┤
441
+ │ │
442
+ │ 📁 Project: Planflow Plugin │
443
+ │ │
444
+ │ ── Activity Feed ────────────────────────────────────────────────────── │
445
+ │ │
446
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
447
+ │ │ ✅ John marked T2.1 as done 5 min ago │ │
448
+ │ └────────────────────────────────────────────────────────────────────────┘ │
449
+ │ │
450
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
451
+ │ │ 💬 Jane commented on T2.3 10 min ago │ │
452
+ │ │ "Looks good! Just one small fix..." │ │
453
+ │ └────────────────────────────────────────────────────────────────────────┘ │
454
+ │ │
455
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
456
+ │ │ 🔄 Bob started working on T3.1 1 hour ago │ │
457
+ │ └────────────────────────────────────────────────────────────────────────┘ │
458
+ │ │
459
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
460
+ │ │ 👤 Jane assigned T2.5 to John 2 hours ago │ │
461
+ │ └────────────────────────────────────────────────────────────────────────┘ │
462
+ │ │
463
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
464
+ │ │ 🎉 Alice joined the project 4 hours ago │ │
465
+ │ └────────────────────────────────────────────────────────────────────────┘ │
466
+ │ │
467
+ │ 📄 Showing 5 of 45 activities │
468
+ │ │
469
+ ├──────────────────────────────────────────────────────────────────────────────┤
470
+ │ │
471
+ │ 💡 Commands: │
472
+ │ • /pfActivity --limit 20 View more activity │
473
+ │ • /pfActivity T2.1 View task activity │
474
+ │ • /pfActivity --type tasks Filter by type │
475
+ │ │
476
+ ╰──────────────────────────────────────────────────────────────────────────────╯
477
+ ```
478
+
479
+ **Task-Specific Activity Card:**
480
+
481
+ ```
482
+ ╭──────────────────────────────────────────────────────────────────────────────╮
483
+ │ 📊 Activity for T2.1 │
484
+ ├──────────────────────────────────────────────────────────────────────────────┤
485
+ │ │
486
+ │ 📋 Task: Implement login API │
487
+ │ │
488
+ │ ── Activity Feed ────────────────────────────────────────────────────── │
489
+ │ │
490
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
491
+ │ │ ✅ John marked as done 5 min ago │ │
492
+ │ └────────────────────────────────────────────────────────────────────────┘ │
493
+ │ │
494
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
495
+ │ │ 💬 Jane commented 30 min ago │ │
496
+ │ │ "Ready for review!" │ │
497
+ │ └────────────────────────────────────────────────────────────────────────┘ │
498
+ │ │
499
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
500
+ │ │ 💬 John commented 1 hour ago │ │
501
+ │ │ "Almost done, just testing..." │ │
502
+ │ └────────────────────────────────────────────────────────────────────────┘ │
503
+ │ │
504
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
505
+ │ │ 🔄 John started working 3 hours ago │ │
506
+ │ └────────────────────────────────────────────────────────────────────────┘ │
507
+ │ │
508
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
509
+ │ │ 👤 Jane assigned to John 1 day ago │ │
510
+ │ └────────────────────────────────────────────────────────────────────────┘ │
511
+ │ │
512
+ ├──────────────────────────────────────────────────────────────────────────────┤
513
+ │ │
514
+ │ 💡 Commands: │
515
+ │ • /pfComment T2.1 "Your message" Add a comment │
516
+ │ • /pfComments T2.1 View all comments │
517
+ │ │
518
+ ╰──────────────────────────────────────────────────────────────────────────────╯
519
+ ```
520
+
521
+ ---
522
+
523
+ ### Step 7: No Activity Card
524
+
525
+ Display when no activity is found.
526
+
527
+ ```
528
+ ╭──────────────────────────────────────────────────────────────────────────────╮
529
+ │ 📊 Recent Activity │
530
+ ├──────────────────────────────────────────────────────────────────────────────┤
531
+ │ │
532
+ │ 📁 Project: Planflow Plugin │
533
+ │ │
534
+ │ ╭─────────────────────────────────────────────────────────────────────╮ │
535
+ │ │ │ │
536
+ │ │ 📭 No recent activity found. │ │
537
+ │ │ │ │
538
+ │ ╰─────────────────────────────────────────────────────────────────────╯ │
539
+ │ │
540
+ │ Activity will appear when team members: │
541
+ │ • Update task statuses │
542
+ │ • Add comments │
543
+ │ • Assign tasks │
544
+ │ • Join or leave the project │
545
+ │ │
546
+ ╰──────────────────────────────────────────────────────────────────────────────╯
547
+ ```
548
+
549
+ ---
550
+
551
+ ## Error Handling
552
+
553
+ ### Task Not Found (404)
554
+
555
+ ```
556
+ ╭──────────────────────────────────────────────────────────────────────────────╮
557
+ │ ❌ ERROR │
558
+ ├──────────────────────────────────────────────────────────────────────────────┤
559
+ │ │
560
+ │ Task not found: T2.1 │
561
+ │ │
562
+ │ Make sure the task exists. Run /pfSyncPush to sync your local tasks. │
563
+ │ │
564
+ ╰──────────────────────────────────────────────────────────────────────────────╯
565
+ ```
566
+
567
+ ### Invalid Activity Type
568
+
569
+ ```
570
+ ╭──────────────────────────────────────────────────────────────────────────────╮
571
+ │ ❌ ERROR │
572
+ ├──────────────────────────────────────────────────────────────────────────────┤
573
+ │ │
574
+ │ Invalid activity type: "{type}" │
575
+ │ │
576
+ │ Valid types: tasks, comments, assignments, team │
577
+ │ │
578
+ ╰──────────────────────────────────────────────────────────────────────────────╯
579
+ ```
580
+
581
+ ### Network Error
582
+
583
+ ```
584
+ ╭──────────────────────────────────────────────────────────────────────────────╮
585
+ │ ❌ ERROR │
586
+ ├──────────────────────────────────────────────────────────────────────────────┤
587
+ │ │
588
+ │ Failed to fetch activity. │
589
+ │ │
590
+ │ Please check your internet connection and try again. │
591
+ │ │
592
+ ╰──────────────────────────────────────────────────────────────────────────────╯
593
+ ```
594
+
595
+ ### Authentication Error (401)
596
+
597
+ ```
598
+ ╭──────────────────────────────────────────────────────────────────────────────╮
599
+ │ ❌ ERROR │
600
+ ├──────────────────────────────────────────────────────────────────────────────┤
601
+ │ │
602
+ │ Authentication failed. Your token may have expired. │
603
+ │ │
604
+ │ 💡 Run /pfLogin to re-authenticate. │
605
+ │ │
606
+ ╰──────────────────────────────────────────────────────────────────────────────╯
607
+ ```
608
+
609
+ ---
610
+
611
+ ## Complete Implementation Flow
612
+
613
+ ```
614
+ /pfActivity [args]
615
+
616
+
617
+ ┌────────────────────────────────────────┐
618
+ │ Step 0: Load config and translations │
619
+ └─────────────────┬──────────────────────┘
620
+
621
+
622
+ ┌────────────────────────────────────────┐
623
+ │ Step 1: Parse arguments │
624
+ │ - taskId (optional) │
625
+ │ - limit (default: 10) │
626
+ │ - type filter (optional) │
627
+ └─────────────────┬──────────────────────┘
628
+
629
+
630
+ ┌────────────────────────────────────────┐
631
+ │ Step 2: Check for --help flag │
632
+ │ → Show usage if needed │
633
+ └─────────────────┬──────────────────────┘
634
+
635
+
636
+ ┌────────────────────────────────────────┐
637
+ │ Step 3: Check prerequisites │
638
+ │ - Authenticated? │
639
+ │ - Project linked? │
640
+ └─────────────────┬──────────────────────┘
641
+
642
+
643
+ ┌────────────────────────────────────────┐
644
+ │ Step 4: Fetch activity from API │
645
+ │ GET /projects/:id/activity │
646
+ │ GET /projects/:id/tasks/:id/activity │
647
+ └─────────────────┬──────────────────────┘
648
+
649
+
650
+ ┌────────────────────────────────────────┐
651
+ │ Step 5: Format activity items │
652
+ │ - Apply icons │
653
+ │ - Format relative time │
654
+ │ - Build messages │
655
+ └─────────────────┬──────────────────────┘
656
+
657
+
658
+ ┌────────────────────────────────────────┐
659
+ │ Step 6/7: Display activity card │
660
+ │ - Activity feed or no activity │
661
+ └────────────────────────────────────────┘
662
+ ```
663
+
664
+ ---
665
+
666
+ ## Translation Keys
667
+
668
+ ```json
669
+ {
670
+ "commands": {
671
+ "activity": {
672
+ "title": "📊 Activity Feed",
673
+ "recentActivity": "📊 Recent Activity",
674
+ "taskActivity": "📊 Activity for {taskId}",
675
+ "projectLabel": "📁 Project: {name}",
676
+ "taskLabel": "📋 Task: {name}",
677
+ "feedTitle": "Activity Feed",
678
+ "showingCount": "📄 Showing {count} of {total} activities",
679
+ "noActivity": "📭 No recent activity found.",
680
+ "noActivityHint": "Activity will appear when team members:",
681
+ "noActivityHint1": "Update task statuses",
682
+ "noActivityHint2": "Add comments",
683
+ "noActivityHint3": "Assign tasks",
684
+ "noActivityHint4": "Join or leave the project",
685
+ "usage": "Usage",
686
+ "usageMain": "/pfActivity Show recent project activity",
687
+ "usageTask": "/pfActivity <task-id> Show activity for specific task",
688
+ "usageLimit": "/pfActivity --limit <n> Show more entries (default: 10, max: 50)",
689
+ "usageType": "/pfActivity --type <type> Filter by activity type",
690
+ "types": "Activity Types",
691
+ "typeTasks": "tasks - Task status changes",
692
+ "typeComments": "comments - Comment activity",
693
+ "typeAssignments": "assignments - Task assignments",
694
+ "typeTeam": "team - Team membership changes",
695
+ "examples": "Examples",
696
+ "commands": "Commands",
697
+ "viewMore": "/pfActivity --limit 20 View more activity",
698
+ "viewTask": "/pfActivity T2.1 View task activity",
699
+ "filterType": "/pfActivity --type tasks Filter by type",
700
+ "addComment": "/pfComment {taskId} \"Your message\" Add a comment",
701
+ "viewComments": "/pfComments {taskId} View all comments",
702
+ "invalidType": "Invalid activity type: \"{type}\"",
703
+ "validTypes": "Valid types: tasks, comments, assignments, team",
704
+ "taskNotFound": "Task not found: {taskId}",
705
+ "taskNotFoundHint": "Make sure the task exists. Run /pfSyncPush to sync your local tasks.",
706
+ "fetchFailed": "Failed to fetch activity.",
707
+ "checkConnection": "Please check your internet connection and try again."
708
+ }
709
+ }
710
+ }
711
+ ```
712
+
713
+ ---
714
+
715
+ ## Success Criteria
716
+
717
+ A successful /pfActivity command should:
718
+ - ✅ Load config and check authentication
719
+ - ✅ Parse task ID, limit, and type from arguments
720
+ - ✅ Make appropriate API call (project or task activity)
721
+ - ✅ Format activity items with icons and relative times
722
+ - ✅ Display activity in formatted card
723
+ - ✅ Handle empty activity gracefully
724
+ - ✅ Handle errors with helpful messages
725
+ - ✅ Show usage on --help or missing project