---
name: tasks
description: Fetch my tasks from LazyTasks for this project
argument-hint: [optional: task ID to view details, or "update ID status" to change status]
---

# LazyTasks Integration

Fetch, view, and update tasks assigned to me from LazyTasks for this project.

## IMPORTANT: Use a background sub-agent

**Do NOT run API calls in the main session.** Launch a background Agent (subagent_type: general-purpose, run_in_background: true) with the instructions below. The main session stays responsive while the agent works.

## Agent prompt template

Give the background agent these instructions:

---

### Configuration

- Read `.claude/lazytasks.json` from the repo root for `project_id`
- Credentials from env vars: `LAZYTASKS_DOMAIN`, `LAZYTASKS_EMAIL`, `LAZYTASKS_PASSWORD`
- Token cache file: `/tmp/.lazytasks_token.json`

### Authentication (with token caching)

Before authenticating, check if a cached token exists and is still valid:

```bash
source ~/.zshrc 2>/dev/null

# Check cached token
if [ -f /tmp/.lazytasks_token.json ]; then
  CACHED=$(python3 -c "
import json, time, base64
with open('/tmp/.lazytasks_token.json') as f:
    cache = json.load(f)
token = cache.get('token','')
try:
    payload = token.split('.')[1]
    payload += '=' * (4 - len(payload) % 4)
    data = json.loads(base64.b64decode(payload))
    exp = data.get('exp', 0)
    if time.time() < exp - 300:  # valid with 5min buffer
        print('VALID')
    else:
        print('EXPIRED')
except:
    print('EXPIRED')
  ")
fi

if [ "$CACHED" = "VALID" ]; then
  TOKEN=$(python3 -c "import json; print(json.load(open('/tmp/.lazytasks_token.json'))['token'])")
  USER_ID=$(python3 -c "import json; print(json.load(open('/tmp/.lazytasks_token.json'))['user_id'])")
  USER_NAME=$(python3 -c "import json; print(json.load(open('/tmp/.lazytasks_token.json'))['user_name'])")
else
  # Fresh login
  RESPONSE=$(curl -s -X POST "${LAZYTASKS_DOMAIN}/wp-json/lazytasks/api/v2/jwt-auth/login" \
    -H "Content-Type: application/json" \
    -d "{\"email\": \"${LAZYTASKS_EMAIL}\", \"password\": \"${LAZYTASKS_PASSWORD}\"}")
  TOKEN=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")

  # Extract user info and cache
  python3 -c "
import sys, json, base64
token = '$TOKEN'
payload = token.split('.')[1]
payload += '=' * (4 - len(payload) % 4)
data = json.loads(base64.b64decode(payload))['data']
cache = {'token': token, 'user_id': str(data['user_id']), 'user_name': data['name']}
with open('/tmp/.lazytasks_token.json', 'w') as f:
    json.dump(cache, f)
print(data['user_id'])
print(data['name'])
  " | { read USER_ID; read USER_NAME; }
fi
```

### API Endpoints

**List my tasks:**
```
GET ${LAZYTASKS_DOMAIN}/wp-json/lazytasks/api/v1/tasks/by/user/${USER_ID}
```
- Response: `data.allTasks` — dict keyed by task ID or list
- Filter where `project_id` matches value from `lazytasks.json`
- **Slim payload** — does NOT include `comments`, `commentsAndLogActivities`, `attachments`, or `members`. Use it for the listing only. To view a single task with its full payload, use the `show` endpoint below.

**Show full task (with comments, activity log, attachments, members):**
```
GET ${LAZYTASKS_DOMAIN}/wp-json/lazytasks/api/v1/tasks/show/${TASK_ID}
```
- Use this whenever you need the `comments` array, the `commentsAndLogActivities` audit feed, attachments, or full member data for a single task.
- The `by/user` listing is intentionally slim and omits these fields.

**Update a task:**
```
POST ${LAZYTASKS_DOMAIN}/wp-json/lazytasks/api/v3/tasks/edit/${TASK_ID}
```
Body (all fields optional, send only what's changing):
```json
{
  "name": "Task title",
  "description": "HTML description",
  "internal_status": {"id": STATUS_ID, "name": "Status Name"},
  "priority": {"id": PRIORITY_ID, "name": "Priority Name"},
  "updated_by": USER_ID
}
```

**Add a comment to a task:**
```
POST ${LAZYTASKS_DOMAIN}/wp-json/lazytasks/api/v2/comments/create
```
Body:
```json
{
  "user_id": USER_ID,
  "user_name": "USER_NAME",
  "commentable_id": "TASK_ID",
  "commentable_type": "task",
  "content": "<p>Comment text here</p>",
  "mention_users": [],
  "created_at": "Just now"
}
```

### Project Status IDs (project 6)

| ID  | Name        |
|-----|-------------|
| 16  | Active      |
| 17  | In Progress |
| 18  | Complete    |
| 109 | Reassign    |

### Project Priority IDs (project 6)

| ID  | Name     |
|-----|----------|
| 59  | Critical |
| 19  | High     |
| 110 | Urgent   |
| 18  | Medium   |
| 17  | Low      |

### Actions based on arguments

**No argument → list tasks:**
- Fetch and filter tasks for this project
- Return formatted table: `# | ID | Title | Status | Priority | Section`

**Task ID (e.g., "2963") → view details:**
- GET the `tasks/show/${TASK_ID}` endpoint (NOT `by/user`) — only the show endpoint returns the full payload with `comments` and `commentsAndLogActivities`.
- Return: name, description (strip HTML), status, priority, section, dates, members, assigned_to, createdBy
- **Always include all comments** from the `comments` array — show commenter name, date, and content (strip HTML). This is critical for seeing SQA replies. If `comments` is empty, say so explicitly. If `commentsAndLogActivities` has assignment-history entries worth showing, include a brief summary.

**"update ID status" (e.g., "update 2963 in-progress") → change status:**
- Map status name: active→16, in-progress→17, complete→18, reassign→109
- POST to v3 edit endpoint with `internal_status` and `updated_by`
- Return confirmation

**"update ID priority LEVEL" (e.g., "update 2963 priority high") → change priority:**
- Map priority: critical→59, high→19, urgent→110, medium→18, low→17
- POST with `priority` and `updated_by`
- Return confirmation

**"comment ID message" (e.g., "comment 2408 Need clarification: what FB app credentials should be used?") → add comment:**
- POST to comments/create endpoint with user_id, user_name, commentable_id, content wrapped in `<p>` tags
- Return confirmation

**"assign ID user" (e.g., "assign 2963 nusrat") → reassign task:**
- Known users: nusrat→{id:11, name:"Nusrat Jahan Heer"}, saiful→{id:15, name:"Md. Saiful Hossain"}
- POST to v3 edit endpoint with `assigned_to` object and `updated_by`
- Return confirmation

### Completion ≠ Reassignment

When marking a task Complete, **do NOT reassign it** in the same call:
- POST only `internal_status: {id:18, name:"Complete"}` + `updated_by`. Omit `assigned_to`.
- The task stays assigned to the current developer (id 15, Md. Saiful Hossain) after completion.

**Reassignment is a separate, batched step** that happens only when the app is actually delivered — e.g., a new APK/AAB is sent to SQA, a Firebase build is pushed, or the branch is merged and deployed. Only then call v3 edit with:
```json
{"assigned_to": {"id": 11, "name": "Nusrat Jahan Heer"}, "updated_by": USER_ID}
```
(or whoever the task creator is — fall back to the creator lookup if `createdBy_id` ≠ 11).

**Why the split:** completing a task locally and delivering an installable build happen at different times. Reassigning on every commit makes SQA's queue noisy before anything is testable.

**Trigger phrases for reassignment:**
- "send the app to [name]"
- "reassign [task id] to [name]"
- "deliver this batch"
- "we pushed the build"
- "ship to nusrat" / "/ship"
The user should always explicitly request this — never infer it from a "mark complete" alone.

**For the full ship workflow, use the `/ship` skill** (`.claude/skills/ship/SKILL.md`) — it restarts the white-label build pipeline in the supervisor clone at `~/projects/appza_community` and then batch-reassigns the shipped tasks. Single-task reassign ("assign 2963 nusrat") still goes through this skill's `assign ID user` action.

### Rules

- Never expose tokens or passwords in output
- User ID extracted from JWT, not hardcoded
- If auth fails, delete /tmp/.lazytasks_token.json and retry once with fresh login
- If retry also fails, return error suggesting user check `.zshrc` credentials

---

## After agent returns

**Listing:** Display table, ask "Which task do you want to work on?"

**Viewing:** Display details including comments, ask "Ready to start working on this?"

**Updating:** Confirm the change was made.

**When user picks a task to work on:**
1. Set status to "In Progress" via background agent
2. Read task description + comments as requirements
3. Begin implementation
4. After the user confirms the fix works AND the change is pushed: **MANDATORY** — post a summary comment on the LazyTask via background agent. Do not wait to be asked. The comment is the SQA hand-off note; without it SQA doesn't know what was changed, what to retest, or which sub-issues are addressed.

### Mandatory task comment — what to write

For every LazyTask you ship work on, post a single comment that includes:
- Which sub-issues from the task description / latest SQA reply are now addressed (number them so SQA can match against their report).
- The user-visible behaviour change in one sentence per item — not implementation jargon.
- For multi-issue tasks: explicitly call out anything you intentionally did NOT change and why, so SQA isn't surprised.
- Mention that it's in the next build (or specify build channel if known).

Skip the comment ONLY if the user explicitly says "don't comment" for that task. The skill agent's "comment ID message" form is the API to call; pass content wrapped in `<p>` tags or a `<p>…</p><ol>…</ol>` structure for multi-item summaries.
