add multiple new tasks, validation not implemented

This commit is contained in:
Robin Olsen
2026-02-25 15:14:09 +01:00
parent e7b644c307
commit 8d6b71d1c4
14 changed files with 1165 additions and 20 deletions

View File

@@ -40,8 +40,35 @@ func init() {
task.RegisterTask("coding_task", func(app *service.App) task.Tasker { task.RegisterTask("coding_task", func(app *service.App) task.Tasker {
return tasks.NewCodingTask(app) return tasks.NewCodingTask(app)
}) })
task.RegisterTask("git-task", func(app *service.App) task.Tasker { task.RegisterTask("git_task", func(app *service.App) task.Tasker {
return tasks.NewGitTask(app) return tasks.NewGitTask(app)
}) })
task.RegisterTask("sprint_planning", func(app *service.App) task.Tasker {
return tasks.NewSprintPlanningTask(app)
})
task.RegisterTask("issue_triage", func(app *service.App) task.Tasker {
return tasks.NewIssueTriageTask(app)
})
task.RegisterTask("milestone_tracking", func(app *service.App) task.Tasker {
return tasks.NewMilestoneTrackingTask(app)
})
task.RegisterTask("dependency_management", func(app *service.App) task.Tasker {
return tasks.NewDependencyManagementTask(app)
})
task.RegisterTask("team_capacity", func(app *service.App) task.Tasker {
return tasks.NewTeamCapacityTask(app)
})
task.RegisterTask("report_generation", func(app *service.App) task.Tasker {
return tasks.NewReportGenerationTask(app)
})
task.RegisterTask("stakeholder_update", func(app *service.App) task.Tasker {
return tasks.NewStakeholderUpdateTask(app)
})
task.RegisterTask("priority_management", func(app *service.App) task.Tasker {
return tasks.NewPriorityManagementTask(app)
})
task.RegisterTask("backlog_refinement", func(app *service.App) task.Tasker {
return tasks.NewBacklogRefinementTask(app)
})
} }

View File

@@ -0,0 +1,128 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const backlogRefinementDescription = `You are tasked with backlog refinement.
The product backlog has become cluttered with old and unclear issues. You need to groom the backlog:
1. Review all issues in the backlog
2. Identify stale or obsolete issues (older items that are no longer relevant)
3. Update issue descriptions for clarity where needed
4. Close issues that are duplicates or no longer applicable
5. Reprioritize issues based on current business value
6. Ensure remaining issues are well-defined and actionable
Focus on making the backlog a reliable source of upcoming work.`
type BacklogRefinementTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewBacklogRefinementTask(app *service.App) *BacklogRefinementTask {
return &BacklogRefinementTask{app: app, done: false}
}
func (t *BacklogRefinementTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/refinement-task-stats.json")
}
func (t *BacklogRefinementTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Backlog Refinement Task").
WithDescription(backlogRefinementDescription).
WithTimeToComplete("12m").
WithDifficulty("Medium")
}
func (t *BacklogRefinementTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many issues did you close or update during refinement?").
Options(
huh.NewOption("1-2", 1),
huh.NewOption("3-4", 2),
huh.NewOption("5+", 3),
),
),
)
}
func (t *BacklogRefinementTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
refinementIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Old feature request: Fax integration").
WithDescription("Allow sending reports via fax. DEPRECATED - nobody uses fax anymore").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("User profile page").
WithDescription("Create page for users to view profile. DUPLICATE of user-management epic").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Mobile app redesign").
WithDescription("Redesign mobile interface with modern UI patterns. Still relevant, needs clarity").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Legacy data export tool").
WithDescription("Tool for exporting data in old format. OBSOLETE - format no longer supported").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("API v1 documentation").
WithDescription("Document old API version. DEPRECATED - migrating to v2").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Customer feedback system").
WithDescription("Build system for collecting user feedback. HIGH VALUE - prioritize").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, refinementIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Backlog Refinement Session").
WithDescription(backlogRefinementDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *BacklogRefinementTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Backlog refinement task completed!", 5*time.Second)
}

View File

@@ -15,8 +15,20 @@ import (
const codingDescription = `You are tasked with writing a simple function. const codingDescription = `You are tasked with writing a simple function.
Write a function that takes two integers and returns their sum. This task will test your ability to write clean, working code.
The function should be named "Add" and be part of the "coding" package.`
Your task:
1. Review the requirements below
2. Write a function that takes two integers and returns their sum
3. The function should be named "Add"
4. The function should be part of the "coding" package
5. Save your code to the code.txt file
Requirements:
- Function name: Add
- Parameters: two integers
- Return value: integer (sum of the two inputs)
- Package: coding`
var textFileContent = codingDescription + ` var textFileContent = codingDescription + `
Please write your code below this line! Please write your code below this line!

View File

@@ -12,11 +12,17 @@ import (
) )
const description = `You are tasked with creating a new issue in the project management system. const description = `You are tasked with creating a new issue in the project management system.
This task will test your ability to use the issue creation workflow effectively. This task will test your ability to use the issue creation workflow effectively.
Assign this task to yourself and start creating a new issue. Your task:
Make sure to fill out all the necessary details, including the title and description. 1. Create a new issue with a clear title
Once you have created the issue, mark it as closed to complete the task.` 2. Add a detailed description explaining what needs to be done
3. Assign the issue to yourself
4. Mark the issue as in-progress when you start working on it
5. Close the issue once you've completed the work
Make sure to fill out all the necessary details to help others understand the work item.`
type CreateIssueTask struct { type CreateIssueTask struct {
done bool done bool
@@ -46,7 +52,9 @@ func (t *CreateIssueTask) Setup(ctx context.Context) error {
} }
t.setupTask = models.NewBaseIssue(). t.setupTask = models.NewBaseIssue().
WithTitle("Create a New Issue").WithDescription(description).Build() WithTitle("Create a New Issue").
WithDescription(description).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupTask, "") return t.app.Issues.CreateIssue(ctx, t.setupTask, "")
} }
@@ -57,11 +65,9 @@ func (t *CreateIssueTask) Validate(ctx context.Context) (bool, error) {
return false, err return false, err
} }
/* Not implemented yet, as assigning to self is not supported in the current implementation if t.setupTask.Assignee == "" {
if t.setupTask.Assignee != "Me" {
return false, fmt.Errorf("issue not assigned to self") return false, fmt.Errorf("issue not assigned to self")
} }
*/
if len(issues) < 2 { if len(issues) < 2 {
return false, fmt.Errorf("issue not created") return false, fmt.Errorf("issue not created")
@@ -87,11 +93,9 @@ func (t *CreateIssueTask) Validate(ctx context.Context) (bool, error) {
return false, fmt.Errorf("issue description is empty") return false, fmt.Errorf("issue description is empty")
} }
/* Not implemented yet, as assigning to self is not supported in the current implementation if createdIssue.Assignee == "" {
if createdIssue.Assignee != "Me" {
return false, fmt.Errorf("issue not assigned to self") return false, fmt.Errorf("issue not assigned to self")
} }
*/
if createdIssue.Status != models.StatusClosed { if createdIssue.Status != models.StatusClosed {
return false, fmt.Errorf("issue status is not closed") return false, fmt.Errorf("issue status is not closed")

View File

@@ -0,0 +1,120 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const dependencyManagementDescription = `You are tasked with managing issue dependencies.
Several issues in your project have dependencies on other issues. You need to:
1. Review the dependency chain described in issue descriptions
2. Identify issues that are blocked by others
3. Prioritize work on foundational issues (those that unblock others)
4. Update issue statuses to reflect dependency resolution
5. Ensure no circular dependencies exist
Resolving dependencies in the right order is critical for efficient team workflow.`
type DependencyManagementTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewDependencyManagementTask(app *service.App) *DependencyManagementTask {
return &DependencyManagementTask{app: app, done: false}
}
func (t *DependencyManagementTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/dependency-task-stats.json")
}
func (t *DependencyManagementTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Dependency Management Task").
WithDescription(dependencyManagementDescription).
WithTimeToComplete("15m").
WithDifficulty("Hard")
}
func (t *DependencyManagementTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many foundational issues did you identify?").
Options(
huh.NewOption("1", 1),
huh.NewOption("2", 2),
huh.NewOption("3+", 3),
),
),
)
}
func (t *DependencyManagementTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
depIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Setup database connection").
WithDescription("Configure database connection pool.").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Define API contract").
WithDescription("Create OpenAPI spec.").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Implement user repository").
WithDescription("Implement data access layer for user management.").
WithPriority(2).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Create user endpoints").
WithDescription("REST API for users.").
WithPriority(2).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Build user profile UI").
WithDescription("Frontend user profile page.").
WithPriority(3).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, depIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Dependency Management").
WithDescription(dependencyManagementDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *DependencyManagementTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Dependency management task completed!", 5*time.Second)
}

View File

@@ -15,10 +15,18 @@ import (
"github.com/go-git/go-git/v6" "github.com/go-git/go-git/v6"
) )
var ( const gitTaskDescription = `You are tasked with performing a Git operation.
gitTaskDescription = `You are tasked with performing a Git operation.
This task will test your ability to use Git effectively.` This task will test your ability to use Git effectively within a project management workflow.
)
Your task:
1. Initialize or open a Git repository
2. Review the current repository status
3. Make appropriate changes to complete the task
4. Commit your changes with a meaningful message
5. Update the task status to reflect completion
The repository has been initialized in ./task/.git/ for you to work with.`
type GitTask struct { type GitTask struct {
setupIssue *models.Issue setupIssue *models.Issue
@@ -68,9 +76,11 @@ func (t *GitTask) Setup(ctx context.Context) error {
[]byte("This is a Git task. Please perform a Git operation here."), []byte("This is a Git task. Please perform a Git operation here."),
os.FileMode(os.O_WRONLY|os.O_CREATE)) os.FileMode(os.O_WRONLY|os.O_CREATE))
t.setupIssue = models.NewBaseIssue(). t.setupIssue = models.NewIssueBuilder().
WithTitle("Git Task Setup Issue"). WithTitle("Git Task Setup Issue").
WithDescription(gitTaskDescription).Build() WithDescription(gitTaskDescription).
WithIssueType(models.TypeTask).
Build()
if err := t.app.Issues.CreateIssue(ctx, t.setupIssue, ""); err != nil { if err := t.app.Issues.CreateIssue(ctx, t.setupIssue, ""); err != nil {
return err return err

View File

@@ -0,0 +1,120 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const issueTriageDescription = `You are tasked with triaging incoming issues.
The support team has submitted several bug reports and feature requests that need to be reviewed and prioritized. Your job is to:
1. Review each incoming issue
2. Assign appropriate priority
3. Set the correct status
4. Identify if it's a bug, feature, or task
5. Leave comments explaining your decisions
Make decisions quickly but thoughtfully. Not everything is high priority!`
type IssueTriageTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewIssueTriageTask(app *service.App) *IssueTriageTask {
return &IssueTriageTask{app: app, done: false}
}
func (t *IssueTriageTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/triage-task-stats.json")
}
func (t *IssueTriageTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Issue Triage Task").
WithDescription(issueTriageDescription).
WithTimeToComplete("12m").
WithDifficulty("Medium")
}
func (t *IssueTriageTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many Critical priority issues did you identify?").
Options(
huh.NewOption("0", 0),
huh.NewOption("1", 1),
huh.NewOption("2", 2),
huh.NewOption("3+", 3),
),
),
)
}
func (t *IssueTriageTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
triageIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("App crashes on login").
WithDescription("Users report the app crashes immediately after entering credentials. Affects all users on Android 12. Needs urgent attention.").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Dark mode support").
WithDescription("Users requesting dark mode theme for better night time usage. Nice to have feature.").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Database timeout errors").
WithDescription("Intermittent timeouts when querying large datasets. Needs investigation.").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Add export to CSV feature").
WithDescription("Sales team needs ability to export reports to CSV format.").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Security: Password reset vulnerability").
WithDescription("Reported by security audit - password reset tokens don't expire. Critical security issue.").
WithPriority(0).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, triageIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Issue Triage Queue").
WithDescription(issueTriageDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *IssueTriageTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Issue triage task completed!", 5*time.Second)
}

View File

@@ -0,0 +1,120 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const milestoneTrackingDescription = `You are tasked with managing a project milestone.
The "Q1 Release" milestone is approaching and you need to ensure all issues are on track.
Review the milestone issues and:
1. Identify issues at risk of missing the deadline
2. Update issue statuses to reflect current progress
3. Flag any blockers or dependencies causing delays
4. Close completed issues
5. Provide status updates for stakeholder visibility
The milestone deadline is 2 weeks away. Some issues have dependencies that need to be resolved first.`
type MilestoneTrackingTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewMilestoneTrackingTask(app *service.App) *MilestoneTrackingTask {
return &MilestoneTrackingTask{app: app, done: false}
}
func (t *MilestoneTrackingTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/milestone-task-stats.json")
}
func (t *MilestoneTrackingTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Milestone Tracking Task").
WithDescription(milestoneTrackingDescription).
WithTimeToComplete("10m").
WithDifficulty("Easy")
}
func (t *MilestoneTrackingTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many issues did you identify as at-risk?").
Options(
huh.NewOption("0", 0),
huh.NewOption("1-2", 1),
huh.NewOption("3+", 2),
),
),
)
}
func (t *MilestoneTrackingTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
milestoneIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Core API endpoints").
WithDescription("Implement REST API for core functionality. COMPLETED").
WithPriority(1).
WithStatus(models.StatusClosed).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Frontend dashboard").
WithDescription("Create main dashboard UI. In progress - 80%% complete").
WithPriority(1).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("User management module").
WithDescription("Depends on Core API. Add user CRUD operations. Currently blocked").
WithPriority(2).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Analytics reporting").
WithDescription("Generate usage analytics reports. Not started yet").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Email notifications").
WithDescription("Setup email service for alerts. 50%% complete").
WithPriority(2).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, milestoneIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Q1 Release Milestone Tracking").
WithDescription(milestoneTrackingDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *MilestoneTrackingTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Milestone tracking task completed!", 5*time.Second)
}

View File

@@ -0,0 +1,120 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const priorityManagementDescription = `You are tasked with managing issue priorities.
A critical production issue has been reported. You need to rebalance the current sprint priorities:
1. Review all current issues and their priorities
2. Identify the most urgent production issue
3. Reprioritize existing work to accommodate the urgent fix
4. Defer lower priority items if necessary
5. Update the team on priority changes via comments
6. Ensure the critical path is clear for the urgent fix
The production database is experiencing intermittent connection failures affecting all users.`
type PriorityManagementTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewPriorityManagementTask(app *service.App) *PriorityManagementTask {
return &PriorityManagementTask{app: app, done: false}
}
func (t *PriorityManagementTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/priority-task-stats.json")
}
func (t *PriorityManagementTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Priority Management Task").
WithDescription(priorityManagementDescription).
WithTimeToComplete("8m").
WithDifficulty("Easy")
}
func (t *PriorityManagementTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many issues did you reprioritize or comment on?").
Options(
huh.NewOption("1-2", 1),
huh.NewOption("3-4", 2),
huh.NewOption("5+", 3),
),
),
)
}
func (t *PriorityManagementTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
priorityIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Database connection failures").
WithDescription("PRODUCTION CRITICAL: Intermittent DB connection failures affecting all users. Needs immediate attention.").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("UI theme updates").
WithDescription("Update color scheme per new brand guidelines. Currently in progress but can wait.").
WithPriority(1).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Feature: Dark mode").
WithDescription("Add dark mode toggle to settings. Nice to have, can be deferred.").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("API rate limiting").
WithDescription("Add rate limiting to public API endpoints. Security enhancement.").
WithPriority(2).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Documentation updates").
WithDescription("Update API documentation for v2 endpoints. Can be deferred.").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, priorityIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Priority Rebalancing").
WithDescription(priorityManagementDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *PriorityManagementTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Priority management task completed!", 5*time.Second)
}

View File

@@ -0,0 +1,122 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const reportGenerationDescription = `You are tasked with generating a project status report.
The stakeholders need a weekly status update. Review the current project state and:
1. Identify completed issues since last report
2. Count issues in progress and their status
3. Note any blocked items and blockers
4. Calculate velocity
5. Flag any risks or concerns
6. Update the project status
Add summary comments to at least 3 key issues that stakeholders should know about.`
type ReportGenerationTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewReportGenerationTask(app *service.App) *ReportGenerationTask {
return &ReportGenerationTask{app: app, done: false}
}
func (t *ReportGenerationTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/report-task-stats.json")
}
func (t *ReportGenerationTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Status Report Generation").
WithDescription(reportGenerationDescription).
WithTimeToComplete("10m").
WithDifficulty("Easy")
}
func (t *ReportGenerationTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("What is the overall project status?").
Options(
huh.NewOption("On Track", 1),
huh.NewOption("At Risk", 2),
huh.NewOption("Off Track", 3),
),
),
)
}
func (t *ReportGenerationTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
reportIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("User login feature").
WithDescription("Allow users to login with email/password.").
WithPriority(1).
WithStatus(models.StatusClosed).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Password reset").
WithDescription("Email-based password reset flow. In Progress").
WithPriority(2).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Database optimization").
WithDescription("Optimize slow queries identified in profiling.").
WithPriority(1).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Mobile responsive design").
WithDescription("Make UI work on mobile devices.").
WithPriority(2).
WithStatus(models.StatusClosed).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Third-party API integration").
WithDescription("Waiting for vendor API documentation.").
WithPriority(1).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
}
for _, issue := range reportIssues {
if err := t.app.Issues.CreateIssue(ctx, issue, ""); err != nil {
return err
}
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Weekly Status Report").
WithDescription(reportGenerationDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *ReportGenerationTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Report generation task completed!", 5*time.Second)
}

View File

@@ -0,0 +1,121 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const sprintPlanningDescription = `You are tasked with sprint planning.
A new sprint is starting and you need to organize the backlog.
You will be given a list of issues with different priorities and dependencies.
Your task:
1. Review the backlog issues
2. Select which issues to include in the sprint
3. Update issue statuses to move items into the sprint
4. Address any blocked or dependent issues
5. Prioritize high-priority items
The goal is to create a realistic sprint plan that delivers value while respecting team capacity.`
type SprintPlanningTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewSprintPlanningTask(app *service.App) *SprintPlanningTask {
return &SprintPlanningTask{app: app, done: false}
}
func (t *SprintPlanningTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/sprint-planning-stats.json")
}
func (t *SprintPlanningTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Sprint Planning Task").
WithDescription(sprintPlanningDescription).
WithTimeToComplete("15m").
WithDifficulty("Medium")
}
func (t *SprintPlanningTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many issues did you select for the sprint?").
Options(
huh.NewOption("2-3 issues", 1),
huh.NewOption("4-5 issues", 2),
huh.NewOption("6+ issues", 3),
),
),
)
}
func (t *SprintPlanningTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
backlogIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Implement user authentication").
WithDescription("Add login/logout functionality. Priority: High").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Design database schema").
WithDescription("Create tables for users and orders. Priority: High").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Setup CI/CD pipeline").
WithDescription("Configure automated testing and deployment. Currently blocked by server setup").
WithPriority(2).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Create API documentation").
WithDescription("Document all REST endpoints. Priority: Low").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Implement search functionality").
WithDescription("Depends on database schema. Priority: Medium").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, backlogIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Sprint Planning - Week 1").
WithDescription(sprintPlanningDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *SprintPlanningTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Sprint planning task completed!", 5*time.Second)
}

View File

@@ -0,0 +1,115 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const stakeholderUpdateDescription = `You are tasked with preparing stakeholder updates.
A key stakeholder has requested an update on the progress of their requested features.
You need to:
1. Identify issues related to the stakeholder's requests (marked with "stakeholder" in description)
2. Review the current status of each issue
3. Provide clear, non-technical status updates via comments
4. Highlight any blockers or delays
5. Set realistic expectations for delivery
6. Close completed items with completion notes
The stakeholder is interested in the Dashboard Enhancement and Export Features specifically.`
type StakeholderUpdateTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewStakeholderUpdateTask(app *service.App) *StakeholderUpdateTask {
return &StakeholderUpdateTask{app: app, done: false}
}
func (t *StakeholderUpdateTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/stakeholder-task-stats.json")
}
func (t *StakeholderUpdateTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Stakeholder Update Task").
WithDescription(stakeholderUpdateDescription).
WithTimeToComplete("10m").
WithDifficulty("Easy")
}
func (t *StakeholderUpdateTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How satisfied will the stakeholder be with this update?").
Options(
huh.NewOption("Very satisfied", 1),
huh.NewOption("Satisfied", 2),
huh.NewOption("Neutral", 3),
huh.NewOption("Concerned", 4),
),
),
)
}
func (t *StakeholderUpdateTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
stakeholderIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Dashboard Enhancement - Charts").
WithDescription("Add interactive charts to the main dashboard (stakeholder request). COMPLETED").
WithPriority(1).
WithStatus(models.StatusClosed).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Dashboard Enhancement - Filters").
WithDescription("Add date range filters to dashboard (stakeholder request). In Progress").
WithPriority(2).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Export to PDF").
WithDescription("Allow exporting reports to PDF format (stakeholder request). In Progress").
WithPriority(1).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Export to Excel").
WithDescription("Allow exporting data to Excel format (stakeholder request). BLOCKED - waiting for library approval").
WithPriority(2).
WithStatus(models.StatusBlocked).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, stakeholderIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Stakeholder Update Preparation").
WithDescription(stakeholderUpdateDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *StakeholderUpdateTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Stakeholder update task completed!", 5*time.Second)
}

View File

@@ -0,0 +1,127 @@
package tasks
import (
"context"
"time"
"github.com/LazyBachelor/LazyPM/internal/models"
"github.com/LazyBachelor/LazyPM/internal/service"
"github.com/LazyBachelor/LazyPM/pkg/task"
taskui "github.com/LazyBachelor/LazyPM/pkg/task/ui"
"github.com/charmbracelet/huh"
)
const teamCapacityDescription = `You are tasked with managing team capacity.
You have a team of 4 developers with varying skill and availability.
Review the upcoming sprint workload and:
1. Review assigned issues and their priorities
2. Identify overloaded team members based on issue assignments
3. Rebalance workload to match capacity
4. Consider vacations and time off mentioned in issue descriptions
5. Ensure critical tasks have coverage
Team member Alice is on vacation next week (mentioned in her issues). Bob can only work 50% time due to other commitments.`
type TeamCapacityTask struct {
done bool
app *service.App
setupIssue *models.Issue
}
func NewTeamCapacityTask(app *service.App) *TeamCapacityTask {
return &TeamCapacityTask{app: app, done: false}
}
func (t *TeamCapacityTask) Config() task.Config {
return BaseConfig().WithStatisticsStoragePath("./.pm/capacity-task-stats.json")
}
func (t *TeamCapacityTask) Details() taskui.TaskDetails {
return BaseDetails().
WithTitle("Team Capacity Management").
WithDescription(teamCapacityDescription).
WithTimeToComplete("12m").
WithDifficulty("Medium")
}
func (t *TeamCapacityTask) Questions(interfaceType task.InterfaceType) taskui.Questions {
return BaseQuestions(interfaceType).With(
huh.NewGroup(
huh.NewSelect[int]().
Title("How many issues did you reassign or update?").
Options(
huh.NewOption("0", 0),
huh.NewOption("1-2", 1),
huh.NewOption("3+", 2),
),
),
)
}
func (t *TeamCapacityTask) Setup(ctx context.Context) error {
if err := ClearIssues(t.app); err != nil {
return err
}
capacityIssues := []*models.Issue{
models.NewIssueBuilder().
WithTitle("Authentication module").
WithDescription("Implement OAuth2 flow. Assigned to: Alice (on vacation next week)").
WithPriority(1).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Payment integration").
WithDescription("Integrate Stripe API. Assigned to: Alice (on vacation next week)").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Dashboard widgets").
WithDescription("Create reusable widget components. Assigned to: Bob (50% capacity)").
WithPriority(2).
WithStatus(models.StatusInProgress).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("API rate limiting").
WithDescription("Add rate limiting middleware. Assigned to: Bob (50% capacity)").
WithPriority(2).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Data migration").
WithDescription("Migrate legacy data to new schema. Assigned to: Charlie (full capacity)").
WithPriority(3).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
models.NewIssueBuilder().
WithTitle("Bug fixes batch").
WithDescription("Fix reported bugs from QA. Assigned to: Diana (full capacity)").
WithPriority(1).
WithStatus(models.StatusOpen).
WithIssueType(models.TypeTask).
Build(),
}
if err := t.app.Issues.CreateIssues(ctx, capacityIssues, ""); err != nil {
return err
}
t.setupIssue = models.NewBaseIssue().
WithTitle("Team Capacity Planning").
WithDescription(teamCapacityDescription).
Build()
return t.app.Issues.CreateIssue(ctx, t.setupIssue, "")
}
func (t *TeamCapacityTask) Validate(ctx context.Context) (bool, error) {
return EndTaskWithTimeout(&t.done, "Team capacity task completed!", 5*time.Second)
}

View File

@@ -15,7 +15,6 @@ func NewIssueBuilder() *IssueBuilder {
func NewBaseIssue() *IssueBuilder { func NewBaseIssue() *IssueBuilder {
return NewIssueBuilder(). return NewIssueBuilder().
WithID("pm-abc").
WithTitle("Basic Issue"). WithTitle("Basic Issue").
WithDescription("Basic Description"). WithDescription("Basic Description").
WithStatus(StatusOpen). WithStatus(StatusOpen).