- name
- ado-timesheet-report
- description
- Generate a summarized report of hours logged from work items during a specified week.
- disable-model-invocation
- true
# Generate Weekly Timesheet Report
Generate a summarized report of hours logged from work items during a specified week, with flexible filtering options for closed, worked on, or both types of tasks. Report is organized in a hierarchical tree structure by Feature > User Story > Task.
## Instructions
**CRITICAL**: This command MUST NOT accept any arguments. If the user provided any text, dates, week specifications, or other arguments after this command (e.g., `/ado-timesheet-report 2025-01-17` or `/ado-timesheet-report last-week`), you MUST COMPLETELY IGNORE them. Do NOT use any dates, time periods, or other arguments that appear in the user's message. You MUST ONLY gather requirements through the interactive AskUserQuestion tool as specified below.
**BEFORE DOING ANYTHING ELSE**: Validate Azure DevOps configuration in CLAUDE.md, then use the AskUserQuestion tool to gather report parameters. DO NOT skip these steps even if the user provided arguments after the command.
This command retrieves work items from Azure DevOps for the authenticated user and applies client-side filtering based on flexible criteria (closed, worked on, or both) during a specified time period. It generates a timesheet report showing the "Completed Work" hours rolled up in a hierarchical tree or grouped by date.
### Phase 1: Validate Azure DevOps Configuration
Before proceeding with report generation, verify that Azure DevOps configuration exists:
1. Use the **Read tool** to read `CLAUDE.md` from the project root
2. If the file doesn't exist OR doesn't contain an "## Azure DevOps" section:
- Display the following error message:
```
❌ Azure DevOps configur ation not found
CLAUDE.md does not contain Azure DevOps configuration.
Please run /ado-init first to configure Azure DevOps settings for this project.
The /ado-init command will:
- Configure your organization, project, and team
- Set up Area Path and Iteration Path defaults
- Define naming conventions and work item guidelines
- Optionally configure the Azure DevOps MCP server
```
- **STOP** and do not proceed further
3. If Azure DevOps section exists:
- Parse the CLAUDE.md content to extract configuration values:
- Organization name (look for text after 'Organization:**')
- Project name (look for text after 'Project:**')
- Store these values for use in work item queries
- Proceed to Phase 2
**IMPORTANT**:
- Use **Read tool** to check CLAUDE.md - DO NOT use bash commands
- The entire command should STOP if Azure DevOps configuration is not found
- Do not prompt the user for configuration values - they must run /ado-init first
### Phase 2: Gather Report Parameters
Collect report parameters from the user using the AskUserQuestion tool to ask multiple questions at once.
**Step 1 - Report Configuration (4 questions combined):**
Use the **AskUserQuestion tool** to ask all report configuration questions at once:
```json
{
"questions": [
{
"question": "What is your organization's work week definition?",
"header": "Week Type",
"multiSelect": false,
"options": [
{
"label": "Sunday-Saturday",
"description": "Sunday through Saturday week"
},
{
"label": "Monday-Sunday",
"description": "ISO standard week (Monday through Sunday)"
}
]
},
{
"question": "Which time period would you like to report on?",
"header": "Time Period",
"multiSelect": false,
"options": [
{
"label": "Current week",
"description": "Report on the current week"
},
{
"label": "Last week",
"description": "Report on last week"
},
{
"label": "Specific week",
"description": "Provide a specific end date for the week"
}
]
},
{
"question": "What types of tasks would you like to include in the report?",
"header": "Task Filter",
"multiSelect": false,
"options": [
{
"label": "Closed only",
"description": "Only tasks that were closed during the time period"
},
{
"label": "Worked on only",
"description": "Only tasks that were worked on (but not closed) during the time period"
},
{
"label": "Both",
"description": "Both closed and worked-on tasks during the time period"
}
]
},
{
"question": "Which date field should be used to filter tasks within the time period? (If you selected 'Worked on only', 'Changed Date' is recommended)",
"header": "Date Field",
"multiSelect": false,
"options": [
{
"label": "Closed Date",
"description": "When the task was marked as closed (best for 'closed only' filter)"
},
{
"label": "Changed Date",
"description": "When the task was last updated (best for 'worked on' or 'both' filters)"
}
]
}
]
}
```
Wait for the user's response before proceeding.
**Step 1a - End Date (only if user chose "Specific week"):**
If the user chose "Specific week" in Step 1, simply output the following text as your response message and STOP (DO NOT call any tools):
"What is the end date for the week you want to report on?
Please provide the date in YYYY-MM-DD format (e.g., 2025-01-17 for the week ending January 17, 2025)."
Wait for the user's next message with the end date before proceeding.
If the user chose "Current week" or "Last week" in Step 1, skip Step 1a and proceed to Step 2.
**Step 2 - Display Options (3 questions combined):**
After handling the optional end date, use the **AskUserQuestion tool** to ask display-related questions:
```json
{
"questions": [
{
"question": "What level of detail would you like in the report?",
"header": "Verbosity",
"multiSelect": false,
"options": [
{
"label": "Level 1",
"description": "Work Item ID & Hours Only"
},
{
"label": "Level 2",
"description": "Work Item ID, Title, and Hours"
},
{
"label": "Level 3",
"description": "Work Item ID, Title, Description, and Hours"
}
]
},
{
"question": "How would you like to organize the report?",
"header": "Grouping",
"multiSelect": false,
"options": [
{
"label": "By date",
"description": "Group by day of the week with work items under each date"
},
{
"label": "By hierarchy",
"description": "Group by Feature > User Story > Task (traditional tree view)"
},
{
"label": "By date with hierarchy",
"description": "Group by day, then show Feature > User Story > Task within each day"
}
]
},
{
"question": "Whose hours would you like to report on?",
"header": "User",
"multiSelect": false,
"options": [
{
"label": "Current user",
"description": "Current authenticated user (default)"
},
{
"label": "Specific team member",
"description": "Provide a specific team member's name"
}
]
}
]
}
```
Wait for the user's response before proceeding.
**Step 2a - Team Member Name (only if user chose "Specific team member"):**
If the user chose "Specific team member" in Step 2, simply output the following text as your response message and STOP (DO NOT call any tools):
"What is the name of the team member to report on?
Please provide the full name as it appears in Azure DevOps (e.g., 'John Smith')."
Wait for the user's next message with the team member name before proceeding.
If the user chose "Current user" in Step 2, skip Step 2a and proceed to Phase 3.
**IMPORTANT**:
- Use **AskUserQuestion tool** twice:
- Step 1: Ask 4 report configuration questions together (week definition, time period, task filter type, date field)
- Step 2: Ask 3 display option questions together (verbosity level, grouping mode, user selection)
- Use simple text output for conditional free-form inputs:
- Step 1a: End date (only if "Specific week" was selected)
- Step 2a: Team member name (only if "Specific team member" was selected)
- Wait for the user's response after each step before proceeding
- Store all collected values for use in Phase 3, 4, 5, and 6:
- Week definition (Monday-Sunday or Sunday-Saturday)
- Time period (Current week, Last week, or Specific week)
- End date (if Specific week selected)
- Task filter type (Closed only, Worked on only, or Both)
- Date field (Closed Date or Changed Date)
- Verbosity level (Level 1, Level 2, or Level 3)
- Grouping mode (By hierarchy, By date, or By date with hierarchy)
- User selection (Current user or team member name)
- Calculate the date range based on user's choices:
- For "Current week": Calculate current week's start and end dates
- For "Last week": Calculate last week's start and end dates
- For "Specific week": Calculate the week's start date from the provided end date
- Week calculation should use the week definition from Step 1
### Phase 3: Calculate Date Range
Based on the user's time period selection and week definition, calculate the start and end dates:
1. **Determine today's date** using the current system date
- The system provides the current date in `<env>` section as "Today's date: YYYY-MM-DD"
- This is in ISO 8601 format where YYYY-MM-DD means Year-Month-Day
- For example: 2025-10-23 is October 23, 2025 (NOT January 23)
- **IMPORTANT**: Trust this date exactly as provided - do NOT second-guess or reinterpret the format
- The month is always the middle number (01=January, 02=February, ... 10=October, 11=November, 12=December)
2. **Calculate date range** based on user selections:
**Step 1: Determine today's day of the week using system commands**
Use the **Bash tool** to execute a platform-specific command. Check the platform from `<env>`:
- **If platform is `win32` (Windows)**:
Execute PowerShell command using the **Bash tool**:
```bash
powershell -Command "(Get-Date 'YYYY-MM-DD').DayOfWeek.value__"
```
Replace `YYYY-MM-DD` with today's date from `<env>`.
This returns a number 0-6 where:
- 0 = Sunday
- 1 = Monday
- 2 = Tuesday
- 3 = Wednesday
- 4 = Thursday
- 5 = Friday
- 6 = Saturday
- **If platform is `darwin` (Mac) or `linux`**:
Execute bash command:
```bash
date -d "YYYY-MM-DD" +%u
```
Replace `YYYY-MM-DD` with today's date from `<env>`.
This returns a number 1-7 where:
- 1 = Monday
- 2 = Tuesday
- 3 = Wednesday
- 4 = Thursday
- 5 = Friday
- 6 = Saturday
- 7 = Sunday
**Step 2: Calculate the date range based on the day of week value**
**For "Current week":**
- **If week is Monday-Sunday**:
- **On Windows** (day_of_week is 0-6):
- If day_of_week = 1 (Monday): days_to_subtract = 0
- If day_of_week = 2 (Tuesday): days_to_subtract = 1
- If day_of_week = 3 (Wednesday): days_to_subtract = 2
- If day_of_week = 4 (Thursday): days_to_subtract = 3
- If day_of_week = 5 (Friday): days_to_subtract = 4
- If day_of_week = 6 (Saturday): days_to_subtract = 5
- If day_of_week = 0 (Sunday): days_to_subtract = 6
- **On Mac/Linux** (day_of_week is 1-7):
- days_to_subtract = day_of_week - 1
- Start date = Today - days_to_subtract (this gives you the Monday of the current week)
- End date = Start date + 6 days (this gives you the Sunday of the current week)
- **If week is Sunday-Saturday**:
- **On Windows** (day_of_week is 0-6):
- days_to_subtract = day_of_week
- **On Mac/Linux** (day_of_week is 1-7):
- If day_of_week = 7 (Sunday): days_to_subtract = 0
- Otherwise: days_to_subtract = day_of_week
- Start date = Today - days_to_subtract (this gives you the Sunday of the current week)
- End date = Start date + 6 days (this gives you the Saturday of the current week)
**Example for Monday-Sunday week:**
- If today is October 24, 2025 (Friday):
- On Windows: PowerShell returns 5 (Friday)
- days_to_subtract = 4
- On Mac/Linux: bash returns 5 (Friday)
- days_to_subtract = 5 - 1 = 4
- Start date = Oct 24 - 4 days = October 20, 2025 (Monday)
- End date = Oct 20 + 6 days = October 26, 2025 (Sunday)
- **Result: October 20-26, 2025**
**For "Last week":**
- If week is Monday-Sunday:
1. Calculate the current week's Monday using the algorithm above
2. Start date = Current week's Monday - 7 days (Monday of last week)
3. End date = Start date + 6 days (Sunday of last week)
- If week is Sunday-Saturday:
1. Calculate the current week's Sunday using the algorithm above
2. Start date = Current week's Sunday - 7 days (Sunday of last week)
3. End date = Start date + 6 days (Saturday of last week)
**For "Specific week":**
- End date: User-provided date
- If week is Monday-Sunday:
- Validate that the end date is a Sunday
- Start date: 6 days before the end date (the Monday)
- If week is Sunday-Saturday:
- Validate that the end date is a Saturday
- Start date: 6 days before the end date (the Sunday)
3. **Format dates** in ISO 8601 format (YYYY-MM-DD) for use in client-side filtering
**IMPORTANT**:
- All date calculations should be done programmatically (don't ask user for date calculations)
- **CRITICAL**: Use the Bash tool with platform-specific commands to determine day of week
- On Windows (platform: win32): `powershell -Command "(Get-Date 'YYYY-MM-DD').DayOfWeek.value__"` (returns 0-6)
- On Mac/Linux (platform: darwin/linux): `date -d "YYYY-MM-DD" +%u` (returns 1-7)
- DO NOT manually calculate day of week - the system command is authoritative
- **CRITICAL**: Follow the lookup tables exactly for days_to_subtract calculation
- Windows and Mac/Linux use different numbering systems (0-6 vs 1-7)
- Verify your calculation matches the example: Oct 24 (Fri) → Oct 20-26 (Mon-Sun)
- For specific week option, validate that the end date matches the expected day of week using the same system commands
- If validation fails, display helpful error message and ask user to provide correct end date
- Store calculated start_date and end_date for use in Phase 4
### Phase 4: Retrieve and Filter Work Items
Retrieve work items from Azure DevOps and apply client-side filtering based on the user's filter choices:
1. **Retrieve work items** using the **wit_my_work_items** MCP tool:
- `project`: Project name from Phase 1 configuration
- This returns all work items relevant to the authenticated user
- The response includes work item details with all necessary fields
2. **Resolve team member identity** (if "Specific team member" was selected):
- If user chose "Specific team member" in Phase 2:
- Use **core_get_identity_ids** MCP tool to resolve the team member's identity
- `uniqueNames`: Array containing the team member name from Phase 2 (e.g., `["John Smith"]`)
- Extract the identity ID from the response to match against AssignedTo fields
- If user chose "Current user":
- Skip this step and filter by current authenticated user
3. **Filter work items client-side** based on user selections from Phase 2:
**Step 3a - Filter by Completed Work:**
- Keep only work items where `Microsoft.VSTS.Scheduling.CompletedWork` field exists and is greater than 0
- Work items without logged hours should be excluded
**Step 3b - Filter by User Assignment:**
- If "Current user" was selected:
- Keep work items assigned to the current authenticated user
- Compare `System.AssignedTo` field with current user identity
- If "Specific team member" was selected:
- Keep work items assigned to the resolved team member identity
- Compare `System.AssignedTo` field with the identity from step 2
**Step 3c - Determine Date Field to Use:**
- If user chose "Closed Date": Use `Microsoft.VSTS.Common.ClosedDate` field
- If user chose "Changed Date": Use `System.ChangedDate` field
View on GitHub