DEV Community

jelly cri
jelly cri

Posted on

Building PriorityPilot: A CLI Project Manager That Learns From Your Decisions

Ever felt like your project management tool should learn how you actually work instead of forcing you into rigid workflows? That's why I built PriorityPilot β€” a command-line project manager that uses machine learning to adapt to your behavior.

πŸ”— GitHub Repository

The Problem

Traditional project management tools make you manually prioritize tasks, estimate timelines, and adjust plans. But here's the thing: your actions already tell the story. When you start a task, postpone another, or complete something faster than expected, you're giving signals about what matters and how long things actually take.

What if your PM tool could learn from these signals?

What PriorityPilot Does

PriorityPilot is a CLI application that:

  • πŸ“Š Learns your priorities from which tasks you start, complete, or postpone
  • ⏱️ Predicts task durations with confidence intervals (e.g., "3-7 hours, 80% confidence")
  • πŸ” Detects data drift to warn you when its predictions become unreliable
  • πŸ“ˆ Provides analytics on bottlenecks, health metrics, and project trends
  • 🎯 Adapts to your workflow β€” starts neutral, gets smarter over time

All in a fast, keyboard-driven interface with zero cloud dependencies.

The Architecture

Tech Stack

  • Python 3.9+ for core logic
  • scikit-learn for ML models (Gradient Boosting, Random Forest, Ridge Regression)
  • SQLite for local persistence
  • Click (or similar) for CLI structure

Project Structure

PriorityPilot/
β”œβ”€β”€ cli/              # User interface (Basic & Advanced modes)
β”œβ”€β”€ services/         # Business logic & analytics
β”œβ”€β”€ ml/               # ML pipeline (training, inference, features)
β”œβ”€β”€ database/         # SQLite manager
β”œβ”€β”€ models/           # Domain models (Task, Project, Milestone)
β”œβ”€β”€ utils/            # Validation, formatting, import/export
β”œβ”€β”€ ml_models/        # Persisted models (.pkl)
β”œβ”€β”€ ml_training_data/ # Training samples & decision logs
└── exports/          # JSON/Markdown reports
Enter fullscreen mode Exit fullscreen mode

The ML Pipeline: How It Learns

1. Signal Collection

Every user action generates training data:

# When user starts a task
signal = {
    "action": "start",
    "task_id": task.id,
    "priority_boost": +1,  # This task matters now
    "timestamp": datetime.now()
}

# When user postpones a task
signal = {
    "action": "postpone",
    "task_id": task.id,
    "priority_penalty": -1,  # This can wait
    "timestamp": datetime.now()
}

# When user completes a task
signal = {
    "action": "complete",
    "task_id": task.id,
    "actual_duration": 4.5,  # hours
    "estimated_duration": 3.0
}
Enter fullscreen mode Exit fullscreen mode

These signals feed into three models:

2. Priority Model (Gradient Boosting)

Features extracted from each task:

  • Time until due date
  • Estimated complexity
  • Number of dependencies (blocking/blocked)
  • Milestone proximity
  • Historical completion rate
  • Recent activity patterns

Training approach:

  • Uses pairwise comparisons: "Task A was chosen over Task B"
  • Continuous learning as more decisions are logged
  • Falls back to rule-based heuristics with < 10 samples
# Simplified feature extraction
def extract_features(task):
    return {
        'days_until_due': (task.due_date - now).days,
        'estimated_hours': task.estimated_hours,
        'dependency_count': len(task.dependencies),
        'completion_rate': task.project.completion_rate,
        'milestone_weight': 1.0 if task.milestone else 0.0,
        'started_recently': 1.0 if task.started_within(7) else 0.0
    }
Enter fullscreen mode Exit fullscreen mode

3. Time Estimator (Random Forest on Log-Hours)

Why log-hours? Software tasks follow a log-normal distribution β€” most are quick, but outliers can be 10x longer.

# Train on log-transformed durations
X_train = feature_matrix
y_train = np.log1p(actual_durations)  # log(1 + hours)

model = RandomForestRegressor(n_estimators=100)
model.fit(X_train, y_train)

# Predict with confidence intervals
predictions = model.predict(X_test)
std_dev = np.std([tree.predict(X_test) for tree in model.estimators_])

lower_bound = np.expm1(predictions - 1.96 * std_dev)
upper_bound = np.expm1(predictions + 1.96 * std_dev)
Enter fullscreen mode Exit fullscreen mode

This gives estimates like: "4.2 hours (3.1–7.5h, 95% CI)"

4. Drift Detection

Machine learning models degrade over time. PriorityPilot monitors:

  • Feature distribution shift: Are task characteristics changing?
  • Prediction error trends: Is accuracy declining?
  • Sample staleness: Is training data outdated?

When drift exceeds thresholds, the UI warns users and suggests retraining.

Key Features

Adaptive Prioritization

The system starts with neutral heuristics (due date, dependencies) and gradually learns your preferences. If you consistently start tasks marked "Low" priority, it learns that's actually important to you.

Confidence Intervals, Not Point Estimates

Traditional estimators give you "3 hours" β€” but that's rarely accurate. PriorityPilot gives you:

  • Best estimate: 4.2 hours
  • 80% confidence: 3.5–5.5 hours
  • 95% confidence: 2.8–7.1 hours

This helps you plan buffers and communicate realistic timelines.

Two-Speed UI

  • Basic Mode: Fast task CRUD, status updates, minimal friction
  • Advanced Mode: Full analytics, ML insights, export/import, drift reports

Switch between them with one keystroke.

Challenges & Solutions

Challenge 1: Cold Start Problem

Problem: ML needs data, but new users have none.

Solution: Rule-based fallback prioritization (due dates, dependencies, milestone proximity) until ~10 samples collected. The UI clearly shows when ML predictions are active vs. heuristic-based.

Challenge 2: Small Sample Sizes

Problem: Personal projects might only have 20-50 tasks total.

Solution:

  • Pairwise learning (every choice creates training data)
  • Feature engineering to maximize signal
  • Cross-validation with small-sample corrections
  • Explicit warnings when confidence is low

Challenge 3: Model Interpretability

Problem: Users distrust black-box predictions.

Solution: ML insights screen shows:

  • Feature importance (what drives predictions)
  • Model metrics (RΒ², RMSE, MAPE)
  • Drift scores and sample counts
  • Ridge baseline comparison

What I Learned

  1. Implicit feedback is powerful: Users don't want to rate tasks β€” their actions are the data.

  2. Uncertainty quantification matters: Confidence intervals are more useful than point estimates for planning.

  3. Drift detection is non-negotiable: ML in production needs guardrails, even for personal tools.

  4. CLI + ML is underexplored: Most ML tools are web apps, but CLIs can be fast, private, and keyboard-driven.

Try It Yourself

# Clone and setup
git clone https://github.com/Usero0/PriorityPilot.git
cd PriorityPilot
python -m venv .venv
source .venv/bin/activate  # or .venv\Scripts\activate on Windows
pip install -r requirements.txt

# Run
python app.py
Enter fullscreen mode Exit fullscreen mode

Start with creating a project (option 1), add some tasks (option 6), and explore ML features after ~10-15 tasks.

Contribute

PriorityPilot is open source (MIT license). Contributions welcome!

  • πŸ› Report issues
  • πŸ’‘ Suggest features
  • πŸ”§ Submit PRs

Have you tried adaptive ML in your personal tools? What worked and what didn't? Let's discuss in the comments! πŸ‘‡


If you found this interesting, consider starring the repo or sharing with your team!

Top comments (0)