Skip to content

Commit 63f4d0d

Browse files
committed
chore(cleanup): Wave-1e tools recreation and analysis pipeline
1 parent 61a5a30 commit 63f4d0d

9 files changed

Lines changed: 1356 additions & 0 deletions

File tree

.coverage

520 KB
Binary file not shown.

data/learning.db

736 KB
Binary file not shown.

docs/cleanup/wave-1e.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Cleanup Wave-1e Report
2+
3+
This document summarizes the activities and outcomes of Cleanup Wave-1e for the StillMe project. The primary objectives for this wave included near-duplicate refactoring with alias shims, pilot canonical imports, and continued controlled quarantine.
4+
5+
## **PREREQUISITE: Wave-1d PR**
6+
7+
**Manual PR Creation Required:**
8+
- **URL:** https://github.com/anhmtk/stillme_ai_ipc/pull/new/cleanup/wave-1d-safe
9+
- **Title:** `chore(cleanup): Wave-1d feature-coverage + near-dupe detector + quarantine (score ≥ 65)`
10+
- **Base:** `main`
11+
- **Head:** `cleanup/wave-1d-safe`
12+
13+
**Description:**
14+
```
15+
Wave-1d cleanup with enhanced coverage, near-duplicate detection, and quarantine of 297 high-score files
16+
17+
## Changes
18+
- Feature-group coverage: 36 modules tested (52.8% success rate)
19+
- Near-duplicate detection: 8,007 clusters from 690 files
20+
- Import graph & dynamic protection: 82 dynamic imports protected
21+
- Rescore with near-dupe: 801 files analyzed, 539 high-risk
22+
- Structural normalization: 2 test files moved to tests/legacy/
23+
- Quarantine: 297 files moved to _attic/ (total 450 files)
24+
25+
## Artifacts
26+
- artifacts/coverage.json
27+
- artifacts/near_dupes.json
28+
- artifacts/import_inbound.json
29+
- artifacts/dynamic_registry_paths.json
30+
- artifacts/redundancy_report.csv
31+
- artifacts/attic_moves.csv
32+
- docs/cleanup/wave-1d.md
33+
- docs/cleanup/near_dupes.md
34+
35+
## Safety
36+
- No permanent deletion, only moves to _attic/
37+
- __init__.py files hard-protected (score 0)
38+
- Rollback capability maintained
39+
- Tracked files only
40+
```
41+
42+
---
43+
44+
## **PHASE 1: NEAR-DUPE FILTERING**
45+
46+
- **Objective**: Filter near-duplicate clusters to identify pilot candidates for refactoring.
47+
- **Approach**: Load `artifacts/near_dupes.json`, apply filtering criteria, and generate pilot set.
48+
49+
## **PHASE 2: ALIAS SHIM & IMPORT REWRITE (PILOT)**
50+
51+
- **Objective**: Create alias shims and rewrite imports to canonical files for pilot clusters.
52+
- **Approach**:
53+
- Create `stillme_compat/` package with deprecation warnings
54+
- Generate import rewrite script
55+
- Apply canonical imports for pilot clusters
56+
57+
## **PHASE 3: RESCORE & QUARANTINE**
58+
59+
- **Objective**: Recalculate scores and quarantine files with relaxed criteria for near-dupes/backups.
60+
- **Approach**:
61+
- Run full analysis pipeline
62+
- Apply dual scoring: 70 for general, 60 for near-dupe/backup
63+
- Execute controlled quarantine
64+
65+
## **PHASE 4: TESTS & CI GUARDS**
66+
67+
- **Objective**: Ensure system stability and add CI gates for near-duplicate prevention.
68+
- **Approach**:
69+
- Run tests and smoke checks
70+
- Update CI with near-dupe gates
71+
- Create baseline for future comparisons
72+
73+
## **PHASE 5: BRANCH & PR**
74+
75+
- **Objective**: Create clean branch and PR with clear diff.
76+
- **Approach**:
77+
- Create `cleanup/wave-1e-safe` from latest main
78+
- Commit in logical groups
79+
- Push and create PR
80+
81+
## **Safety Measures**
82+
83+
- `ALWAYS_PROTECT_PATHS` and `ALWAYS_PROTECT_FILENAMES` are respected
84+
- All import rewrites have alias shims for backward compatibility
85+
- Deprecation warnings for old import paths
86+
- Rollback capability maintained
87+
- Tracked files only

scripts/windows/attic_move.ps1

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# PowerShell script for moving files to _attic/ directory
2+
# Supports CSV input and filtering parameters
3+
4+
param(
5+
[string]$FromCsv = "",
6+
[int]$ScoreMin = 80,
7+
[int]$TopN = 200,
8+
[int]$RelaxedMin = 60,
9+
[switch]$WhatIf = $false
10+
)
11+
12+
# Create _attic directory if it doesn't exist
13+
if (-not (Test-Path "_attic")) {
14+
New-Item -ItemType Directory -Path "_attic" -Force
15+
New-Item -ItemType File -Path "_attic/.gitkeep" -Force
16+
}
17+
18+
# Initialize move log
19+
$moveLog = @()
20+
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
21+
22+
Write-Host "Starting attic move operation..." -ForegroundColor Green
23+
Write-Host " - Score minimum: $ScoreMin" -ForegroundColor Yellow
24+
Write-Host " - Relaxed minimum: $RelaxedMin" -ForegroundColor Yellow
25+
Write-Host " - Top N: $TopN" -ForegroundColor Yellow
26+
Write-Host " - WhatIf: $WhatIf" -ForegroundColor Yellow
27+
28+
if ($FromCsv -and (Test-Path $FromCsv)) {
29+
Write-Host "Reading candidates from CSV: $FromCsv" -ForegroundColor Cyan
30+
31+
$candidates = Import-Csv $FromCsv
32+
$movedCount = 0
33+
$processedCount = 0
34+
35+
foreach ($candidate in $candidates) {
36+
if ($processedCount -ge $TopN) {
37+
break
38+
}
39+
40+
$filePath = $candidate.path
41+
$score = [int]$candidate.redundant_score
42+
$isNearDupe = $candidate.is_near_dupe -eq "True"
43+
$looksBackup = $candidate.looks_backup -eq "True"
44+
$inboundImports = [int]$candidate.inbound_imports
45+
$executedLines = [int]$candidate.executed_lines
46+
$gitTouches = [int]$candidate.git_touches
47+
$daysSinceLastChange = [int]$candidate.days_since_last_change
48+
$isWhitelisted = $candidate.is_whitelisted -eq "True"
49+
$inRegistry = $candidate.in_registry -eq "True"
50+
51+
# Apply decision rules
52+
$meetsGeneralCriteria = $score -ge $ScoreMin
53+
$meetsRelaxedCriteria = $score -ge $RelaxedMin -and ($isNearDupe -or $looksBackup)
54+
55+
# 3-KHÔNG rule
56+
$threeKhong = ($inboundImports -eq 0 -and $executedLines -eq 0 -and $gitTouches -le 1 -and $daysSinceLastChange -gt 180)
57+
58+
# 2-KHÓA rule (protection)
59+
$twoKhoa = -not $isWhitelisted -and -not $inRegistry -and -not $filePath.EndsWith("__init__.py")
60+
61+
if (($meetsGeneralCriteria -or $meetsRelaxedCriteria) -and $threeKhong -and $twoKhoa) {
62+
if (Test-Path $filePath) {
63+
$destPath = "_attic/$filePath"
64+
$destDir = Split-Path $destPath -Parent
65+
66+
if (-not (Test-Path $destDir)) {
67+
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
68+
}
69+
70+
if ($WhatIf) {
71+
Write-Host " [WHATIF] Would move: $filePath -> $destPath (score: $score)" -ForegroundColor Yellow
72+
} else {
73+
try {
74+
Move-Item -Path $filePath -Destination $destPath -Force
75+
Write-Host " Moved: $filePath (score: $score)" -ForegroundColor Green
76+
77+
$moveLog += [PSCustomObject]@{
78+
src = $filePath
79+
dst = $destPath
80+
timestamp = $timestamp
81+
score = $score
82+
reason = if ($meetsRelaxedCriteria) { "relaxed" } else { "general" }
83+
}
84+
85+
$movedCount++
86+
} catch {
87+
Write-Host " Failed to move: $filePath - $($_.Exception.Message)" -ForegroundColor Red
88+
}
89+
}
90+
91+
$processedCount++
92+
} else {
93+
Write-Host " File not found: $filePath" -ForegroundColor Yellow
94+
}
95+
}
96+
}
97+
98+
Write-Host "Move operation complete:" -ForegroundColor Green
99+
Write-Host " - Files processed: $processedCount" -ForegroundColor White
100+
Write-Host " - Files moved: $movedCount" -ForegroundColor White
101+
102+
# Save move log
103+
if ($moveLog.Count -gt 0) {
104+
$logFile = "artifacts/attic_moves.csv"
105+
$logDir = Split-Path $logFile -Parent
106+
if (-not (Test-Path $logDir)) {
107+
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
108+
}
109+
110+
$moveLog | Export-Csv -Path $logFile -NoTypeInformation -Append
111+
Write-Host " - Move log saved to: $logFile" -ForegroundColor White
112+
}
113+
114+
} else {
115+
Write-Host "CSV file not found: $FromCsv" -ForegroundColor Red
116+
Write-Host "Usage: .\attic_move.ps1 -FromCsv path -ScoreMin int -TopN int [-RelaxedMin int] [-WhatIf]" -ForegroundColor Yellow
117+
}
118+
119+
Write-Host "Attic move operation completed!" -ForegroundColor Green

tools/inventory/feature_smoke.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Feature Smoke Test for Coverage Generation
4+
Safely imports modules from specific feature groups to generate coverage data.
5+
"""
6+
7+
import os
8+
import importlib.util
9+
import sys
10+
import pkgutil
11+
import logging
12+
from pathlib import Path
13+
14+
logging.basicConfig(level=logging.INFO, format='%(levelname)s:%(name)s:%(message)s')
15+
logger = logging.getLogger(__name__)
16+
17+
def is_excluded(file_path: str, global_excludes: list) -> bool:
18+
"""Checks if a file path should be excluded based on global exclude patterns."""
19+
path = Path(file_path).as_posix()
20+
for exclude in global_excludes:
21+
if Path(exclude).is_absolute():
22+
if Path(path) == Path(exclude) or Path(path).is_relative_to(Path(exclude)):
23+
return True
24+
else:
25+
if exclude.endswith('/') and f"/{exclude}" in path:
26+
return True
27+
elif exclude.startswith('*') and path.endswith(exclude[1:]):
28+
return True
29+
elif exclude in path:
30+
return True
31+
return False
32+
33+
def smoke_import_modules(root_packages: list[str], global_excludes: list[str]):
34+
"""
35+
Attempts to import all Python modules under the given root packages safely.
36+
Logs warnings for failures but does not stop execution.
37+
"""
38+
imported_count = 0
39+
failed_count = 0
40+
total_modules = 0
41+
42+
# Add current directory to sys.path to ensure local modules are discoverable
43+
sys.path.insert(0, os.getcwd())
44+
45+
all_modules = set()
46+
for root_package in root_packages:
47+
try:
48+
# Attempt to find the path for the root package
49+
spec = importlib.util.find_spec(root_package)
50+
if spec and spec.submodule_search_locations:
51+
root_path = spec.submodule_search_locations[0]
52+
else:
53+
# Fallback for packages not yet installed or in sys.path
54+
root_path = os.path.join(os.getcwd(), *root_package.split('.'))
55+
if not os.path.exists(root_path):
56+
logger.warning(f"Root package path not found for {root_package}. Skipping.")
57+
continue
58+
59+
for importer, modname, ispkg in pkgutil.walk_packages([root_path], prefix=f"{root_package}."):
60+
module_path = os.path.join(importer.path, modname.replace('.', os.sep))
61+
if ispkg:
62+
module_path = os.path.join(module_path, '__init__.py')
63+
else:
64+
module_path += '.py'
65+
66+
if is_excluded(module_path, global_excludes):
67+
logger.debug(f"Excluding module: {modname} ({module_path})")
68+
continue
69+
all_modules.add(modname)
70+
except Exception as e:
71+
logger.warning(f"Could not walk packages for {root_package}: {e}")
72+
73+
total_modules = len(all_modules)
74+
logger.info(f"📦 Found {total_modules} modules to import")
75+
76+
for modname in sorted(list(all_modules)):
77+
try:
78+
importlib.import_module(modname)
79+
imported_count += 1
80+
except (ImportError, SyntaxError, Exception) as e:
81+
logger.warning(f"Could not import {modname}: {e}")
82+
failed_count += 1
83+
84+
logger.info(f"✅ Successfully imported: {imported_count}")
85+
logger.warning(f"❌ Failed to import: {failed_count}")
86+
logger.info(f"📊 Total modules processed: {total_modules}")
87+
88+
if __name__ == "__main__":
89+
from pathlib import Path
90+
REPO_ROOT = Path(__file__).parent.parent.parent
91+
92+
# Define root packages and global excludes as per user's request
93+
ROOT_PACKAGES = ["stillme_core", "stillme_ethical_core"]
94+
GLOBAL_EXCLUDES = [
95+
".git/", ".github/", ".venv/", "venv/", "env/", "site-packages/", "dist/",
96+
"build/", "node_modules/", "artifacts/", "reports/", "htmlcov",
97+
"__pycache__/", "*.egg-info/", ".sandbox/"
98+
]
99+
100+
logger.info("🔥 Starting smoke import for coverage generation...")
101+
smoke_import_modules(ROOT_PACKAGES, GLOBAL_EXCLUDES)

0 commit comments

Comments
 (0)