Get features that are ready to be worked on. A feature is ready if: - It is not passing - It is not in progress - All its dependencies are satisfied Args: features: List of all feature dicts limit: Maximum number of features to return Returns: List
(features: list[dict], limit: int = 10)
| 353 | |
| 354 | |
| 355 | def get_ready_features(features: list[dict], limit: int = 10) -> list[dict]: |
| 356 | """Get features that are ready to be worked on. |
| 357 | |
| 358 | A feature is ready if: |
| 359 | - It is not passing |
| 360 | - It is not in progress |
| 361 | - All its dependencies are satisfied |
| 362 | |
| 363 | Args: |
| 364 | features: List of all feature dicts |
| 365 | limit: Maximum number of features to return |
| 366 | |
| 367 | Returns: |
| 368 | List of ready features, sorted by priority |
| 369 | """ |
| 370 | passing_ids = {f["id"] for f in features if f.get("passes")} |
| 371 | |
| 372 | ready = [] |
| 373 | for f in features: |
| 374 | if f.get("passes") or f.get("in_progress"): |
| 375 | continue |
| 376 | deps = f.get("dependencies") or [] |
| 377 | if all(dep_id in passing_ids for dep_id in deps): |
| 378 | ready.append(f) |
| 379 | |
| 380 | # Sort by scheduling score (higher = first), then priority, then id |
| 381 | scores = compute_scheduling_scores(features) |
| 382 | ready.sort(key=lambda f: (-scores.get(f["id"], 0), f.get("priority", 999), f["id"])) |
| 383 | |
| 384 | return ready[:limit] |
| 385 | |
| 386 | |
| 387 | def get_blocked_features(features: list[dict]) -> list[dict]: |