| name | milestone-tracker |
| description | Эксперт по отслеживанию milestones. Используй для трекинга прогресса, critical path, статус-репортов и earned value. |
Milestone Tracker Expert
Expert in milestone tracking, project progress monitoring, and critical path analysis for comprehensive project management.
Core Principles
SMART Milestone Definition
- Specific: Clear, unambiguous deliverable
- Measurable: Quantifiable completion criteria
- Achievable: Realistic given resources and constraints
- Relevant: Aligned with project objectives
- Time-bound: Specific deadline
Milestone vs Task
distinction:
milestone:
definition: "Significant checkpoint marking phase completion"
characteristics:
- "Zero duration (point in time)"
- "Binary (complete or not)"
- "Stakeholder visible"
- "Often gates next phase"
examples:
- "Requirements approved"
- "MVP deployed to production"
- "Beta testing complete"
task:
definition: "Work item with duration"
characteristics:
- "Has duration"
- "Can be % complete"
- "May be internal only"
- "Contributes to milestones"
examples:
- "Develop user authentication"
- "Write test cases"
- "Review security requirements"
Milestone Structure Template
milestone_definition:
id: "MS-001"
name: "MVP Launch"
description: "Minimum viable product deployed to production environment"
timing:
baseline_date: "2024-06-30"
current_target: "2024-07-15"
actual_date: null
variance_days: 15
variance_status: "Yellow"
ownership:
accountable: "Product Manager"
responsible: "Engineering Lead"
consulted: ["QA Lead", "DevOps"]
informed: ["Executive Sponsor", "Stakeholders"]
dependencies:
predecessors:
- id: "MS-000"
name: "Development Complete"
type: "Finish-to-Start"
lag: 0
successors:
- id: "MS-002"
name: "Beta Program Start"
type: "Start-to-Start"
lag: 5
acceptance_criteria:
- criterion: "All P1 features functional"
verification: "Feature checklist sign-off"
verifier: "Product Manager"
status: "Pending"
- criterion: "No critical bugs"
verification: "Bug tracker query"
verifier: "QA Lead"
status: "Pending"
- criterion: "Performance benchmarks met"
verification: "Load test results"
verifier: "DevOps"
status: "Pending"
- criterion: "Security scan passed"
verification: "Security report"
verifier: "Security Team"
status: "Pending"
risks:
- risk: "Third-party API integration delay"
probability: "Medium"
impact: "High"
mitigation: "Parallel development with mock API"
owner: "Tech Lead"
- risk: "Resource availability"
probability: "Low"
impact: "Medium"
mitigation: "Cross-training team members"
owner: "Project Manager"
deliverables:
- name: "Production deployment"
type: "System"
location: "AWS Production Environment"
- name: "Release notes"
type: "Document"
location: "Confluence"
- name: "User documentation"
type: "Document"
location: "Help center"
sign_off:
required_approvers:
- role: "Product Manager"
status: "Pending"
date: null
- role: "Engineering Lead"
status: "Pending"
date: null
- role: "QA Lead"
status: "Pending"
date: null
Critical Path Analysis
CPM Algorithm Implementation
from dataclasses import dataclass
from typing import Dict, List, Optional
import heapq
@dataclass
class Activity:
id: str
name: str
duration: int # days
predecessors: List[str]
early_start: int = 0
early_finish: int = 0
late_start: int = 0
late_finish: int = 0
total_float: int = 0
free_float: int = 0
is_critical: bool = False
class CriticalPathCalculator:
def __init__(self, activities: List[Activity]):
self.activities = {a.id: a for a in activities}
self.successors: Dict[str, List[str]] = {a.id: [] for a in activities}
for activity in activities:
for pred in activity.predecessors:
self.successors[pred].append(activity.id)
def calculate(self) -> List[str]:
"""Calculate critical path and return list of critical activity IDs."""
self._forward_pass()
self._backward_pass()
self._calculate_float()
return [aid for aid, a in self.activities.items() if a.is_critical]
def _forward_pass(self):
"""Calculate early start and early finish times."""
# Topological sort
in_degree = {aid: len(a.predecessors) for aid, a in self.activities.items()}
queue = [aid for aid, d in in_degree.items() if d == 0]
while queue:
current_id = queue.pop(0)
current = self.activities[current_id]
# Early finish = Early start + Duration
current.early_finish = current.early_start + current.duration
# Update successors
for succ_id in self.successors[current_id]:
succ = self.activities[succ_id]
succ.early_start = max(succ.early_start, current.early_finish)
in_degree[succ_id] -= 1
if in_degree[succ_id] == 0:
queue.append(succ_id)
def _backward_pass(self):
"""Calculate late start and late finish times."""
# Find project duration
project_duration = max(a.early_finish for a in self.activities.values())
# Initialize late finish for activities with no successors
for aid, a in self.activities.items():
if not self.successors[aid]:
a.late_finish = project_duration
a.late_start = a.late_finish - a.duration
# Reverse topological sort
out_degree = {aid: len(self.successors[aid]) for aid in self.activities}
queue = [aid for aid, d in out_degree.items() if d == 0]
processed = set()
while queue:
current_id = queue.pop(0)
current = self.activities[current_id]
processed.add(current_id)
for pred_id in current.predecessors:
pred = self.activities[pred_id]
if pred.late_finish == 0 or current.late_start < pred.late_finish:
pred.late_finish = current.late_start
pred.late_start = pred.late_finish - pred.duration
# Check if all successors processed
if all(s in processed for s in self.successors[pred_id]):
if pred_id not in queue:
queue.append(pred_id)
def _calculate_float(self):
"""Calculate float values and identify critical activities."""
for activity in self.activities.values():
activity.total_float = activity.late_start - activity.early_start
activity.is_critical = activity.total_float == 0
# Free float calculation
if self.successors[activity.id]:
min_early_start = min(
self.activities[s].early_start
for s in self.successors[activity.id]
)
activity.free_float = min_early_start - activity.early_finish
else:
activity.free_float = activity.total_float
# Usage example
activities = [
Activity("A", "Requirements", 10, []),
Activity("B", "Design", 15, ["A"]),
Activity("C", "Development", 30, ["B"]),
Activity("D", "Testing", 10, ["C"]),
Activity("E", "Documentation", 5, ["B"]),
Activity("F", "Deployment", 5, ["D", "E"]),
]
cpm = CriticalPathCalculator(activities)
critical_path = cpm.calculate()
print("Critical Path:", critical_path)
for aid, activity in cpm.activities.items():
print(f"{activity.name}: ES={activity.early_start}, EF={activity.early_finish}, "
f"LS={activity.late_start}, LF={activity.late_finish}, "
f"TF={activity.total_float}, Critical={activity.is_critical}")
Earned Value Management
EVM Calculations
earned_value_metrics:
baseline_metrics:
BAC: "Budget at Completion - Total planned budget"
PV: "Planned Value - Budgeted cost of work scheduled"
actual_metrics:
AC: "Actual Cost - Cost incurred for work performed"
EV: "Earned Value - Budgeted cost of work performed"
variance_metrics:
CV:
formula: "EV - AC"
interpretation: "Positive = under budget"
SV:
formula: "EV - PV"
interpretation: "Positive = ahead of schedule"
performance_indices:
CPI:
formula: "EV / AC"
interpretation: "1.0 = on budget, >1.0 = under budget"
threshold:
green: ">= 0.95"
yellow: "0.85 - 0.94"
red: "< 0.85"
SPI:
formula: "EV / PV"
interpretation: "1.0 = on schedule, >1.0 = ahead"
threshold:
green: ">= 0.95"
yellow: "0.85 - 0.94"
red: "< 0.85"
forecasting:
EAC_typical:
formula: "BAC / CPI"
use_when: "Current performance expected to continue"
EAC_atypical:
formula: "AC + (BAC - EV)"
use_when: "Variance was one-time, future on plan"
EAC_composite:
formula: "AC + [(BAC - EV) / (CPI × SPI)]"
use_when: "Both cost and schedule performance impact future"
ETC:
formula: "EAC - AC"
interpretation: "Estimate to Complete remaining work"
VAC:
formula: "BAC - EAC"
interpretation: "Variance at Completion"
TCPI:
formula: "(BAC - EV) / (BAC - AC)"
interpretation: "Required performance to meet budget"
EVM Implementation
from dataclasses import dataclass
from typing import Optional
import datetime
@dataclass
class EVMSnapshot:
date: datetime.date
planned_value: float
earned_value: float
actual_cost: float
bac: float # Budget at Completion
@property
def cost_variance(self) -> float:
"""CV = EV - AC"""
return self.earned_value - self.actual_cost
@property
def schedule_variance(self) -> float:
"""SV = EV - PV"""
return self.earned_value - self.planned_value
@property
def cpi(self) -> Optional[float]:
"""Cost Performance Index = EV / AC"""
if self.actual_cost == 0:
return None
return self.earned_value / self.actual_cost
@property
def spi(self) -> Optional[float]:
"""Schedule Performance Index = EV / PV"""
if self.planned_value == 0:
return None
return self.earned_value / self.planned_value
@property
def eac_typical(self) -> Optional[float]:
"""Estimate at Completion (typical variance)"""
if self.cpi is None or self.cpi == 0:
return None
return self.bac / self.cpi
@property
def eac_composite(self) -> Optional[float]:
"""Estimate at Completion (composite)"""
if self.cpi is None or self.spi is None:
return None
if self.cpi * self.spi == 0:
return None
return self.actual_cost + (self.bac - self.earned_value) / (self.cpi * self.spi)
@property
def etc(self) -> Optional[float]:
"""Estimate to Complete"""
eac = self.eac_typical
if eac is None:
return None
return eac - self.actual_cost
@property
def vac(self) -> Optional[float]:
"""Variance at Completion"""
eac = self.eac_typical
if eac is None:
return None
return self.bac - eac
@property
def percent_complete(self) -> float:
"""Progress percentage"""
if self.bac == 0:
return 0
return (self.earned_value / self.bac) * 100
@property
def tcpi(self) -> Optional[float]:
"""To-Complete Performance Index"""
remaining_work = self.bac - self.earned_value
remaining_budget = self.bac - self.actual_cost
if remaining_budget == 0:
return None
return remaining_work / remaining_budget
def status_report(self) -> dict:
"""Generate status summary"""
return {
"date": self.date.isoformat(),
"progress": {
"percent_complete": round(self.percent_complete, 1),
"planned_value": self.planned_value,
"earned_value": self.earned_value,
"actual_cost": self.actual_cost,
},
"variances": {
"cost_variance": round(self.cost_variance, 2),
"schedule_variance": round(self.schedule_variance, 2),
"cv_status": "Under" if self.cost_variance >= 0 else "Over",
"sv_status": "Ahead" if self.schedule_variance >= 0 else "Behind",
},
"indices": {
"cpi": round(self.cpi, 2) if self.cpi else None,
"spi": round(self.spi, 2) if self.spi else None,
},
"forecasts": {
"eac_typical": round(self.eac_typical, 2) if self.eac_typical else None,
"etc": round(self.etc, 2) if self.etc else None,
"vac": round(self.vac, 2) if self.vac else None,
},
"health": self._calculate_health(),
}
def _calculate_health(self) -> str:
"""Determine overall project health"""
cpi = self.cpi or 0
spi = self.spi or 0
if cpi >= 0.95 and spi >= 0.95:
return "Green"
elif cpi >= 0.85 and spi >= 0.85:
return "Yellow"
else:
return "Red"
Status Reporting
Traffic Light System
status_indicators:
green:
criteria:
schedule: "On track or ahead (variance < 5%)"
budget: "On track or under (variance < 5%)"
scope: "No changes or approved changes only"
risks: "All risks mitigated or low impact"
action: "Continue monitoring"
yellow:
criteria:
schedule: "5-15% behind"
budget: "5-15% over"
scope: "Pending change requests"
risks: "Medium risks requiring attention"
action: "Corrective action needed"
red:
criteria:
schedule: ">15% behind"
budget: ">15% over"
scope: "Uncontrolled scope changes"
risks: "High risks threatening success"
action: "Escalation required"
Weekly Status Report Template
weekly_status_report:
header:
project_name: "Project Alpha"
report_date: "2024-03-15"
reporting_period: "2024-03-08 to 2024-03-14"
project_manager: "Jane Smith"
report_number: 12
executive_summary:
overall_status: "Yellow"
summary: |
Project is 5 days behind schedule due to third-party API
integration delays. Recovery plan in place with expected
return to schedule by March 29.
key_messages:
- "MVP features 85% complete"
- "API integration issue being resolved"
- "Additional QA resources approved"
milestone_status:
completed_this_period:
- name: "UI Design Complete"
planned: "2024-03-10"
actual: "2024-03-08"
variance: "-2 days"
upcoming_milestones:
- name: "API Integration Complete"
planned: "2024-03-15"
forecast: "2024-03-20"
variance: "+5 days"
status: "Yellow"
risk: "Dependency on vendor fix"
- name: "Beta Release"
planned: "2024-03-25"
forecast: "2024-03-29"
variance: "+4 days"
status: "Yellow"
risk: "Dependent on API completion"
progress_metrics:
schedule:
planned_progress: "75%"
actual_progress: "70%"
spi: 0.93
status: "Yellow"
budget:
planned_spend: "$150,000"
actual_spend: "$145,000"
cpi: 1.03
status: "Green"
scope:
total_requirements: 45
completed: 38
in_progress: 5
not_started: 2
status: "Green"
accomplishments:
- "Completed all frontend components"
- "Passed security audit"
- "Onboarded 2 additional developers"
- "Resolved 15 defects"
planned_next_period:
- "Complete API integration"
- "Begin end-to-end testing"
- "Finalize user documentation"
- "Prepare beta environment"
issues_and_risks:
active_issues:
- id: "ISS-023"
description: "Third-party API returning incorrect data"
severity: "High"
owner: "Tech Lead"
action: "Vendor ticket escalated, workaround in dev"
target_resolution: "2024-03-18"
risks:
- id: "RSK-012"
description: "Beta testers availability"
probability: "Medium"
impact: "Medium"
mitigation: "Recruiting backup testers"
owner: "Product Manager"
decisions_needed:
- decision: "Approve 2-week schedule extension"
deadline: "2024-03-18"
decision_maker: "Steering Committee"
resource_status:
planned_fte: 8
actual_fte: 9
changes: "+1 QA engineer added"
concerns: "None"
Agile Integration
Sprint-Milestone Alignment
agile_milestone_mapping:
release_planning:
release: "v2.0"
target_date: "2024-06-30"
sprints: 6
sprint_duration: "2 weeks"
milestones:
- milestone: "Feature Complete"
sprint: 4
date: "2024-05-17"
criteria: "All user stories in Done"
- milestone: "Code Freeze"
sprint: 5
date: "2024-05-31"
criteria: "Only bug fixes after this"
- milestone: "Release Candidate"
sprint: 6
date: "2024-06-14"
criteria: "RC deployed to staging"
- milestone: "Production Release"
sprint: 6
date: "2024-06-30"
criteria: "Deployed to production"
sprint_tracking:
sprint: 3
goal: "Complete user authentication and profile features"
story_points:
committed: 34
completed: 28
spillover: 6
velocity:
current: 28
average: 30
trend: "Stable"
burndown:
day_1: 34
day_5: 22
day_10: 6
actual_vs_ideal: "Slightly behind"
Epic Progress Tracking
epic_milestone_tracker:
epic: "User Management System"
status: "In Progress"
milestones:
- name: "User Registration Live"
target: "Sprint 2"
status: "Complete"
features:
- "Email registration"
- "Social login (Google, GitHub)"
- "Email verification"
- name: "Profile Management Live"
target: "Sprint 3"
status: "In Progress"
features:
- "View/edit profile (Done)"
- "Avatar upload (Done)"
- "Privacy settings (In Progress)"
- name: "Admin Controls Live"
target: "Sprint 4"
status: "Not Started"
features:
- "User search"
- "Role management"
- "Bulk operations"
metrics:
story_points_total: 89
story_points_done: 55
percent_complete: 62
remaining_sprints: 2
on_track: true
Tool Integration
Jira Configuration
jira_milestone_setup:
custom_fields:
- name: "Milestone"
type: "Select List (single choice)"
options:
- "MS1: Requirements Complete"
- "MS2: Design Complete"
- "MS3: Development Complete"
- "MS4: Testing Complete"
- "MS5: Release"
- name: "Milestone Date"
type: "Date Picker"
- name: "Milestone Status"
type: "Select List (single choice)"
options:
- "On Track"
- "At Risk"
- "Delayed"
- "Complete"
filters:
milestone_view:
jql: "project = PROJ AND 'Milestone' is not EMPTY ORDER BY 'Milestone Date' ASC"
at_risk_milestones:
jql: "project = PROJ AND 'Milestone Status' = 'At Risk'"
dashboard_gadgets:
- type: "Filter Results"
filter: "Upcoming Milestones"
columns: ["Key", "Summary", "Milestone", "Milestone Date", "Status"]
- type: "Two Dimensional Filter Statistics"
x_axis: "Milestone"
y_axis: "Status"
Gantt Chart Data Structure
from dataclasses import dataclass
from datetime import date
from typing import List, Optional
@dataclass
class GanttTask:
id: str
name: str
start_date: date
end_date: date
progress: float # 0-100
dependencies: List[str]
is_milestone: bool = False
color: Optional[str] = None
resource: Optional[str] = None
def generate_gantt_data(milestones: List[dict]) -> List[GanttTask]:
"""Convert milestone data to Gantt chart format."""
tasks = []
for ms in milestones:
task = GanttTask(
id=ms['id'],
name=ms['name'],
start_date=ms['baseline_date'] if ms['is_milestone']
else ms['start_date'],
end_date=ms['baseline_date'] if ms['is_milestone']
else ms['end_date'],
progress=100 if ms['status'] == 'Complete' else ms.get('progress', 0),
dependencies=ms.get('predecessors', []),
is_milestone=ms['is_milestone'],
color=_status_to_color(ms['status']),
resource=ms.get('owner')
)
tasks.append(task)
return tasks
def _status_to_color(status: str) -> str:
colors = {
'Complete': '#4CAF50',
'On Track': '#2196F3',
'At Risk': '#FFC107',
'Delayed': '#F44336',
'Not Started': '#9E9E9E'
}
return colors.get(status, '#9E9E9E')
Лучшие практики
- SMART milestones — конкретные, измеримые, достижимые, релевантные, ограниченные во времени
- Clear ownership — каждый milestone должен иметь ответственного
- Regular updates — обновляйте статус минимум еженедельно
- Earned value — используйте EVM для объективной оценки прогресса
- Critical path focus — приоритизируйте задачи на критическом пути
- Risk buffers — закладывайте contingency для сложных milestones