Skip to content

feat: phase 4 collaboration features (comments, followers, tags)#30

Merged
amondnet merged 10 commits into
mainfrom
amondnet/phase-4-collaboration-features
Jun 10, 2026
Merged

feat: phase 4 collaboration features (comments, followers, tags)#30
amondnet merged 10 commits into
mainfrom
amondnet/phase-4-collaboration-features

Conversation

@amondnet

@amondnet amondnet commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Phase 4 collaboration features: task comments (Stories API), follower management, and tag CRUD with task assignment.

Closes #17

Changes

Comments (task comment)

  • task comment add <task-gid> <text> — add a comment; --html flag sends Asana rich text (auto-wrapped in <body>)
  • task comment list <task-gid> — lists user comments only (system stories filtered by resource_subtype)

Followers (task follower)

  • task follower add|remove <task-gid> <user> — accepts numeric GID, email, or me
  • task follower list <task-gid> — via task followers opt_fields (Asana has no standalone endpoint)

Tags (tag, task tag)

  • tag list|create|get|update|delete — full CRUD; workspace falls back to the configured default
  • task tag add|remove|list — tag assignment per task
  • Tag colors validated locally against the Asana palette (friendly names like red are rejected by the API; the CLI fails fast with the valid color list)

Client

  • asana-client: new stories and tags wrappers plus follower/tag operations on tasks (uses StoriesApi, TagsApi, addFollowersForTask/removeFollowerForTask, addTagForTask/removeTagForTask)

Bug fix

  • task/project create & list error handlers referenced a workspace variable scoped inside try, crashing with ReferenceError on any API failure. Hoisted the declaration so errors are reported properly.

Testing

  • Unit tests: 223 pass (bun test test/) — command structure tests for comment/follower/tag, validator tests for user identifier and tag color
  • E2E: tests/e2e/collaboration.test.ts covers comment add/list (plain + rich text), follower add/list/remove, tag CRUD, multi-task tag assignment. Not run locally — the .env PAT returns 401 (expired); pre-existing e2e suites fail the same way
  • Lint clean

Notes

  • CHANGELOG.md is managed by release-please, so no manual entry; the feat: commits will generate it
  • Issue example --color "red" is not accepted by the Asana API — only the dark-*/light-* palette is valid; the CLI validates and lists valid colors

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
asana Ready Ready Preview, Comment Jun 10, 2026 7:20am

Request Review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements collaboration features (Phase 4) for the Asana CLI, introducing commands and subcommands to manage task comments, followers, and tags, along with corresponding API client integrations, input validators, documentation, and E2E/unit tests. The code review identified three key areas for improvement: correcting a potential runtime error in the Asana client where a singular method name (removeFollowerForTask) was used instead of the plural form, throwing a ValidationError instead of directly calling process.exit(1) when updating a tag with no fields specified, and resolving a case-sensitivity issue when validating the HTML <body> tag in comments.

Comment thread src/lib/asana-client.ts
Comment on lines +169 to +173
removeFollowers: async (taskGid: string, followers: string[]) => {
const body = { data: { followers } }
const result = await tasksApiInstance!.removeFollowerForTask(body, taskGid, {})
return result.data
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

[HIGH] removeFollowers 메서드의 API 호출 함수명 오류 가능성

Problem: removeFollowers 메서드에서 tasksApiInstance!.removeFollowerForTask를 호출하고 있습니다. Asana API의 엔드포인트가 /tasks/{task_gid}/removeFollowers이고 addFollowersaddFollowersForTask를 사용하는 점으로 미루어 볼 때, 올바른 메서드명은 복수형인 removeFollowersForTask일 가능성이 높습니다. 단수형을 사용할 경우 런타임에 함수가 존재하지 않아 에러가 발생할 수 있습니다.
Rationale: Asana 노드 라이브러리의 자동 생성된 메서드명은 OpenAPI 스펙의 operationId를 따르므로 복수형(removeFollowersForTask)이 올바릅니다.
Suggestion: removeFollowerForTaskremoveFollowersForTask로 변경하여 런타임 오류를 방지합니다.

Suggested change
removeFollowers: async (taskGid: string, followers: string[]) => {
const body = { data: { followers } }
const result = await tasksApiInstance!.removeFollowerForTask(body, taskGid, {})
return result.data
},
removeFollowers: async (taskGid: string, followers: string[]) => {
const body = { data: { followers } }
const result = await tasksApiInstance!.removeFollowersForTask(body, taskGid, {})
return result.data
},
References
  1. 런타임 오류를 방지하기 위해 외부 라이브러리 API 호출 시 올바른 메서드명을 사용해야 합니다. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[claude] ⏭️ 적용하지 않았습니다 — 제안과 달리 asana SDK v3.1.2에는 removeFollowersForTask가 존재하지 않습니다. 패키지를 직접 확인한 결과 생성된 메서드명은 단수형 removeFollowerForTask뿐이며(node_modules/asana/dist/api/TasksApi.js:1314), 이 메서드가 내부적으로 POST /tasks/{task_gid}/removeFollowers 엔드포인트를 호출합니다. 제안대로 복수형으로 변경하면 오히려 런타임에 함수가 존재하지 않아 에러가 발생합니다. 현재 코드가 올바릅니다. @gemini-code-assist

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인해주셔서 감사합니다. 말씀하신 대로 Asana SDK의 자동 생성된 메서드명은 OpenAPI 스펙의 operationId를 따르며, 해당 버전에서 removeFollowerForTask가 올바른 메서드명임을 확인했습니다. 런타임 오류를 방지하기 위해 현재 코드를 유지하는 것이 맞습니다. 상세한 확인과 피드백 감사합니다.

Comment thread src/commands/tag.ts
Comment thread src/commands/task-comment.ts
…aboration-features

# Conflicts:
#	src/commands/task.ts
#	src/constants/errorIds.ts
#	src/index.ts
#	src/lib/asana-client.ts
#	test/commands/task-update-validation.test.ts
- tag update: throw ValidationError instead of calling process.exit directly
- task comment: case-insensitive <body> detection in ensureHtmlBody
…aboration-features

# Conflicts:
#	src/types/index.ts
@amondnet amondnet merged commit c2528ea into main Jun 10, 2026
5 of 6 checks passed
@pleaseai-bot pleaseai-bot Bot mentioned this pull request Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phase 4: Collaboration Features

1 participant