Check if the project has features in the database. This is used to determine if the initializer agent needs to run. We check the database directly (not via API) since the API server may not be running yet when this check is performed. Returns True if: - features.db exists
(project_dir: Path)
| 27 | |
| 28 | |
| 29 | def has_features(project_dir: Path) -> bool: |
| 30 | """ |
| 31 | Check if the project has features in the database. |
| 32 | |
| 33 | This is used to determine if the initializer agent needs to run. |
| 34 | We check the database directly (not via API) since the API server |
| 35 | may not be running yet when this check is performed. |
| 36 | |
| 37 | Returns True if: |
| 38 | - features.db exists AND has at least 1 feature, OR |
| 39 | - feature_list.json exists (legacy format) |
| 40 | |
| 41 | Returns False if no features exist (initializer needs to run). |
| 42 | """ |
| 43 | # Check legacy JSON file first |
| 44 | json_file = project_dir / "feature_list.json" |
| 45 | if json_file.exists(): |
| 46 | return True |
| 47 | |
| 48 | # Check SQLite database |
| 49 | from autoforge_paths import get_features_db_path |
| 50 | db_file = get_features_db_path(project_dir) |
| 51 | if not db_file.exists(): |
| 52 | return False |
| 53 | |
| 54 | try: |
| 55 | with closing(_get_connection(db_file)) as conn: |
| 56 | cursor = conn.cursor() |
| 57 | cursor.execute("SELECT COUNT(*) FROM features") |
| 58 | count: int = cursor.fetchone()[0] |
| 59 | return bool(count > 0) |
| 60 | except Exception: |
| 61 | # Database exists but can't be read or has no features table |
| 62 | return False |
| 63 | |
| 64 | |
| 65 | def count_passing_tests(project_dir: Path) -> tuple[int, int, int]: |
no test coverage detected