7474 IconCssClass =" (item, _) => item.IconCss"
7575 ToolTip =" GetNavItemTooltip"
7676 AllowSelection =" true"
77- ShowRoot =" false "
77+ ShowRoot =" true "
7878 SelectionChange =" OnNavSelectionChanged" />
7979 </div >
8080 </div >
186186 Text =" Re-assess"
187187 IconCssClass =" fas fa-sync-alt"
188188 CssClass =" @GetStepCssClass(WorkflowStep.Reassess)"
189- IsVisible =" @(_currentView is NavView.PackageDetail or NavView.CategoryDetail or NavView.RuleDetail && _selectedRow is not null )"
189+ IsVisible =" @(_currentView is NavView.Dashboard or NavView. PackageDetail or NavView.CategoryDetail or NavView.RuleDetail)"
190190 IsEnabled =" @(!_isAssessing)"
191- ToolTip =" Re-assess this package"
191+ ToolTip =" @(_currentView == NavView.Dashboard ? " Re-assess all repos " : " Re-assess this package " ) "
192192 Click =" OnToolbarClick" />
193193
194194 <PDToolbarButton Key =" fix"
397397 private PDFileModal ? _fileModal ;
398398 private string ? _localReposRoot ;
399399 private bool _folderSaved ;
400+ private bool _includeInfoInAiPrompt ;
400401
401402 // === Lifecycle ===
402403
414415 _categories = Enum .GetValues <AssessmentCategory >();
415416 _localReposRoot = RuntimeSettings .LocalReposRoot ;
416417 _preferredIdeId = RuntimeSettings .PreferredIdeId ;
418+ _includeInfoInAiPrompt = RuntimeSettings .IncludeInfoInAiPrompt ;
417419
418420 // Load from cache immediately
419421 var cached = Cache .GetCachedRows ();
@@ -624,8 +626,16 @@ else
624626 await FixWithAiAsync ();
625627 break ;
626628 case " reassess" :
627- await ReassessAllAsync ();
628- break ;
629+ if (_currentView == NavView .Dashboard )
630+ {
631+ await ReassessAllReposAsync ();
632+ }
633+ else
634+ {
635+ await ReassessAllAsync ();
636+ }
637+
638+ break ;
629639 case " build" :
630640 await BuildAsync ();
631641 break ;
@@ -1059,12 +1069,27 @@ else
10591069 < / select >
10601070 }
10611071 < / div >
1072+ < div class = " form-group" >
1073+ < label > Include info items in AI prompt < / label >
1074+ < div style = " display: flex; align-items: center; gap: 0.5rem;" >
1075+ < input type = " checkbox" checked = " @_includeInfoInAiPrompt" @onchange = " OnIncludeInfoInAiPromptChanged" / >
1076+ < span style = " color: var(--text-secondary); font-size: 0.85rem;" >
1077+ When unchecked , informational (blue ) items are excluded from the generated AI prompt .
1078+ < / span >
1079+ < / div >
1080+ < / div >
10621081 < / div >
10631082 < / div >
10641083 };
10651084
10661085 // === Dashboard methods ===
10671086
1087+ private void OnIncludeInfoInAiPromptChanged (ChangeEventArgs e )
1088+ {
1089+ _includeInfoInAiPrompt = e .Value is true ;
1090+ RuntimeSettings .SetIncludeInfoInAiPrompt (_includeInfoInAiPrompt );
1091+ }
1092+
10681093 private void OnAutoRefreshTimer (object ? state )
10691094 {
10701095 _ = InvokeAsync (async () =>
@@ -1230,11 +1255,28 @@ else
12301255 EnsureSelectedRowIsCurrent ();
12311256
12321257 _isAssessing = true ;
1233- _progressMessage = $" Assessing {_selectedRow .PackageId }..." ;
1258+ _progressMessage = $" Checking NuGet listing for {_selectedRow .PackageId }..." ;
12341259 StateHasChanged ();
12351260
12361261 try
12371262 {
1263+ // Check whether the package is still listed on NuGet
1264+ var isListed = await Dashboard .IsPackageListedAsync (_selectedRow .PackageId );
1265+ if (! isListed )
1266+ {
1267+ AppendConsole ($" ⚠️ {_selectedRow .PackageId } is no longer listed on NuGet — removing from cache." );
1268+ _rows .RemoveAll (r => string .Equals (r .PackageId , _selectedRow .PackageId , StringComparison .OrdinalIgnoreCase ));
1269+ Cache .RemoveRow (_selectedRow .PackageId );
1270+ _selectedRow = null ;
1271+ _selectedPackageId = null ;
1272+ _currentView = NavView .Dashboard ;
1273+ await RefreshTableAsync ();
1274+ return ;
1275+ }
1276+
1277+ _progressMessage = $" Assessing {_selectedRow .PackageId }..." ;
1278+ StateHasChanged ();
1279+
12381280 if (_selectedRow .IsClonedLocally && _selectedRow .LocalPath is not null )
12391281 {
12401282 await Dashboard .AssessLocalRepositoryAsync (_selectedRow );
@@ -1261,6 +1303,72 @@ else
12611303 }
12621304 }
12631305
1306+ private async Task ReassessAllReposAsync ()
1307+ {
1308+ _isAssessing = true ;
1309+ var assessable = _rows .Where (r => r .RepositoryFullName is not null ).ToList ();
1310+ AppendConsole ($" ▶ Re-assessing {assessable .Count } repos..." );
1311+
1312+ // Mark all pending rows so the tree shows spinners
1313+ foreach (var r in assessable )
1314+ {
1315+ r .IsReassessing = true ;
1316+ }
1317+
1318+ await RefreshTableAsync ();
1319+
1320+ try
1321+ {
1322+ var github = CreateGitHubClient ();
1323+
1324+ for (var i = 0 ; i < assessable .Count ; i ++ )
1325+ {
1326+ var row = assessable [i ];
1327+ _progressMessage = $" Assessing ({i + 1 }/{assessable .Count }): {row .PackageId }..." ;
1328+ StateHasChanged ();
1329+
1330+ try
1331+ {
1332+ if (row .IsClonedLocally && row .LocalPath is not null )
1333+ {
1334+ await Dashboard .AssessLocalRepositoryAsync (row );
1335+ }
1336+ else
1337+ {
1338+ await Dashboard .AssessRepositoryAsync (row , github );
1339+ }
1340+ }
1341+ catch (Exception ex )
1342+ {
1343+ AppendConsole ($" ❌ {row .PackageId }: {ex .Message }" );
1344+ }
1345+
1346+ row .IsReassessing = false ;
1347+ await RefreshTableAsync ();
1348+ }
1349+
1350+ Cache .Update (_rows );
1351+ _lastRefreshUtc = Cache .LastRefreshUtc ;
1352+ AppendConsole ($" ✅ Re-assessed {assessable .Count } repos." );
1353+ }
1354+ catch (Exception ex )
1355+ {
1356+ AppendConsole ($" ❌ Re-assess all failed: {ex .Message }" );
1357+ }
1358+ finally
1359+ {
1360+ // Ensure all rows are cleared in case of early exit
1361+ foreach (var r in assessable )
1362+ {
1363+ r .IsReassessing = false ;
1364+ }
1365+
1366+ _isAssessing = false ;
1367+ _progressMessage = string .Empty ;
1368+ StateHasChanged ();
1369+ }
1370+ }
1371+
12641372 private async Task ReassessCategoryAsync (AssessmentCategory category )
12651373 {
12661374 if (_selectedRow is null )
@@ -1617,7 +1725,7 @@ else
16171725 return ;
16181726 }
16191727
1620- var prompt = DashboardService .GenerateRemediationPrompt (_selectedRow );
1728+ var prompt = DashboardService .GenerateRemediationPrompt (_selectedRow , _includeInfoInAiPrompt );
16211729 if (string .IsNullOrEmpty (prompt ))
16221730 {
16231731 AppendConsole (" ℹ️ No failing rules to resolve." );
@@ -1641,7 +1749,7 @@ else
16411749 return ;
16421750 }
16431751
1644- var prompt = DashboardService .GenerateCategoryRemediationPrompt (_selectedRow , category );
1752+ var prompt = DashboardService .GenerateCategoryRemediationPrompt (_selectedRow , category , _includeInfoInAiPrompt );
16451753 if (string .IsNullOrEmpty (prompt ))
16461754 {
16471755 AppendConsole ($" ℹ️ No failing rules in {category }." );
@@ -1672,9 +1780,8 @@ else
16721780 return false ;
16731781 }
16741782
1675- return _selectedRow .IsWorkingTreeClean == true
1676- && _selectedRow .CurrentBranch == " main"
1677- && _selectedRow .IsSyncedWithOrigin == true ;
1783+ return _selectedRow .CurrentBranch == " main"
1784+ && _selectedRow .IsSyncedWithOrigin != false ;
16781785 }
16791786
16801787 private string ? GetFixBlockReason ()
@@ -1684,16 +1791,6 @@ else
16841791 return " Repository is not cloned locally" ;
16851792 }
16861793
1687- if (_selectedRow .IsWorkingTreeClean == false )
1688- {
1689- return " Working tree has uncommitted changes — commit or stash first" ;
1690- }
1691-
1692- if (_selectedRow .IsWorkingTreeClean is null )
1693- {
1694- return " Working tree status is unknown — re-assess or sync first" ;
1695- }
1696-
16971794 if (_selectedRow .CurrentBranch != " main" )
16981795 {
16991796 return $" Must be on 'main' branch (currently on '{_selectedRow .CurrentBranch ?? " unknown" }')" ;
@@ -1704,11 +1801,6 @@ else
17041801 return " Local branch is not in sync with origin — run Git Sync first" ;
17051802 }
17061803
1707- if (_selectedRow .IsSyncedWithOrigin is null )
1708- {
1709- return " Sync status with origin is unknown — run Git Sync first" ;
1710- }
1711-
17121804 return null ;
17131805 }
17141806
@@ -1918,24 +2010,39 @@ else
19182010 return $" {row .PackageId } — all rules pass ✓ (green = compliant)" ;
19192011 }
19202012
1921- return row .TotalErrors > 0
1922- ? $" {row .PackageId } — {row .TotalErrors } error(s), {row .TotalWarnings } warning(s) (red = errors found)"
1923- : $" {row .PackageId } — {row .TotalWarnings } warning(s) (amber = warnings only)" ;
2013+ if (row .TotalErrors > 0 )
2014+ {
2015+ return $" {row .PackageId } — {row .TotalErrors } error(s), {row .TotalWarnings } warning(s) (red = errors found)" ;
2016+ }
2017+
2018+ return row .TotalWarnings > 0
2019+ ? $" {row .PackageId } — {row .TotalWarnings } warning(s) (amber = warnings only)"
2020+ : $" {row .PackageId } — informational only (blue = info)" ;
19242021
19252022 case NavView .CategoryDetail :
19262023 if (item .IssueCount == 0 )
19272024 {
19282025 return $" {item .Text } — all rules pass" ;
19292026 }
19302027
1931- return item .HasErrors
1932- ? $" {item .Text } — {item .IssueCount } issue(s) including errors"
1933- : $" {item .Text } — {item .IssueCount } warning(s)" ;
2028+ if (item .HasErrors )
2029+ {
2030+ return $" {item .Text } — {item .IssueCount } issue(s) including errors" ;
2031+ }
2032+
2033+ return item .HasWarnings
2034+ ? $" {item .Text } — {item .IssueCount } warning(s)"
2035+ : $" {item .Text } — {item .IssueCount } informational" ;
19342036
19352037 case NavView .RuleDetail :
1936- return item .HasErrors
1937- ? $" {item .Text } — error"
1938- : $" {item .Text } — warning" ;
2038+ if (item .HasErrors )
2039+ {
2040+ return $" {item .Text } — error" ;
2041+ }
2042+
2043+ return item .HasWarnings
2044+ ? $" {item .Text } — warning"
2045+ : $" {item .Text } — informational" ;
19392046
19402047 default :
19412048 return item .Text ;
@@ -1954,9 +2061,14 @@ else
19542061 return " fas fa-cube text-success" ;
19552062 }
19562063
1957- return row .TotalErrors > 0
1958- ? " fas fa-cube text-danger"
1959- : " fas fa-cube text-warning" ;
2064+ if (row .TotalErrors > 0 )
2065+ {
2066+ return " fas fa-cube text-danger" ;
2067+ }
2068+
2069+ return row .TotalWarnings > 0
2070+ ? " fas fa-cube text-warning"
2071+ : " fas fa-cube text-info" ;
19602072 }
19612073
19622074 private bool HasAutoRemediableFailures (AssessmentCategory category )
0 commit comments