Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ if ($CreateDesktopShortcut) {
$Shortcut.IconLocation = "$InstallPath\Envoy.exe,0"
$Shortcut.Description = "Envoy - Job Application Agent"
$Shortcut.Save()
[void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($WshShell)
}

if ($CreateStartMenuShortcut) {
Expand All @@ -82,6 +83,7 @@ if ($CreateStartMenuShortcut) {
$Shortcut.IconLocation = "$InstallPath\Envoy.exe,0"
$Shortcut.Description = "Envoy - Job Application Agent"
$Shortcut.Save()
[void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($WshShell)
}

# Create uninstall registry entry
Expand Down
2 changes: 1 addition & 1 deletion publish.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ if (Test-Path "THIRD-PARTY-NOTICES.md") {
Write-Host "Creating launcher script..." -ForegroundColor Yellow
$StartScriptContent = "@echo off`nchcp 65001 >nul`necho.`necho Envoy Job Application Agent`necho.`necho Starting Envoy...`necho.`n`n:: Check if Ollama is running (optional - only needed for local models)`ncurl -s http://localhost:11434 >nul 2>&1`nif errorlevel 1 (`n echo Note: Ollama is not running. That's fine if you only use cloud LLM providers.`n echo For local LLMs install Ollama: https://ollama.com/download`n echo.`n)`n`n:: Start Envoy`nstart `"`" `"%~dp0Envoy.exe`""

$StartScriptContent | Out-File -FilePath "$PublishPath/Start Envoy.bat" -Encoding UTF8
$StartScriptContent | Out-File -FilePath "$PublishPath/Start Envoy.bat" -Encoding ascii

# Create README
Write-Host "Creating package README..." -ForegroundColor Yellow
Expand Down
6 changes: 3 additions & 3 deletions src/Envoy.Core/Services/CdpBrowserService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ public async Task TypeTextAsync(string nodeId, string text, CancellationToken ct
int vkCode;
if (char.IsLetter(ch))
{
code = $"Key{char.ToUpper(ch)}";
vkCode = (int)char.ToUpper(ch);
code = $"Key{char.ToUpperInvariant(ch)}";
vkCode = (int)char.ToUpperInvariant(ch);
}
else if (char.IsDigit(ch))
{
Expand Down Expand Up @@ -433,7 +433,7 @@ public async Task WaitForEventAsync(string eventName, TimeSpan timeout, Cancella
private async Task ReceiveLoop(CancellationToken ct)
{
var buffer = new byte[131072];
var messageBuilder = new MemoryStream();
using var messageBuilder = new MemoryStream();

while (!ct.IsCancellationRequested && _webSocket?.State == WebSocketState.Open)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Envoy.Core/Services/DomScorer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static class DomScorer
foreach (var candidate in matchable)
{
var score = ScoreCandidate(fingerprint, candidate);
if (score >= bestScore)
if (score > bestScore)
{
bestScore = score;
best = candidate;
Expand Down
1 change: 1 addition & 0 deletions src/Envoy.Core/Services/OllamaService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public OllamaService(ILLMProvider provider, ILogger<OllamaService>? log = null)

public void SwitchProvider(ILLMProvider newProvider)
{
ArgumentNullException.ThrowIfNull(newProvider);
_activeProvider = newProvider;
_log.LogInformation("Switched LLM provider to {Provider} ({ProviderId})", newProvider.DisplayName, newProvider.ProviderId);
}
Expand Down
1 change: 0 additions & 1 deletion src/Envoy.Core/Services/RelocationLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public Task LogAsync(RelocationEntry entry)
// to PR against. Surface it.
_log?.LogWarning(ex, "Failed to write relocation entry for template {TemplateId} field {Field}",
entry.TemplateId, entry.Field);
System.Diagnostics.Debug.WriteLine($"[RelocationLogger] Write failed: {ex.Message}");
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/Envoy.Core/Services/SafetyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private void CheckKeywordDensity(MasterProfile tailored, string jobDescription,

if (resumeWords.Length == 0) return;

var matchCount = jdWords.Count(jd => resumeWords.Any(r => r.Contains(jd, StringComparison.OrdinalIgnoreCase)));
var matchCount = jdWords.Count(jd => resumeWords.Any(r => r.Equals(jd, StringComparison.OrdinalIgnoreCase)));
var density = (double)matchCount / jdWords.Count;

// 30% threshold catches LLM-driven stuffing without flagging the natural
Expand Down Expand Up @@ -318,7 +318,7 @@ private static List<string> ExtractKeywords(string text)
{
var words = text.Split(new[] { ' ', '\n', '\r', '.', ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
var stopWords = new HashSet<string> { "the", "and", "for", "with", "you", "are", "will", "must", "have", "this", "that" };
return words.Where(w => w.Length > 3 && !stopWords.Contains(w.ToLower())).ToList();
return words.Where(w => w.Length > 3 && !stopWords.Contains(w.ToLowerInvariant())).ToList();
}

private static string SerializeResume(MasterProfile profile)
Expand Down
4 changes: 2 additions & 2 deletions src/Envoy.Core/Services/TailoringEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ private static string TruncateAtSentenceBoundary(string text, int maxLength)

private double CalculateMatchScore(MasterProfile tailored, string jobDescription)
{
var resumeText = System.Text.Json.JsonSerializer.Serialize(tailored).ToLower();
var jdWords = jobDescription.ToLower().Split(new[] { ' ', '\n', '\r', '.', ',' }, StringSplitOptions.RemoveEmptyEntries)
var resumeText = System.Text.Json.JsonSerializer.Serialize(tailored).ToLowerInvariant();
var jdWords = jobDescription.ToLowerInvariant().Split(new[] { ' ', '\n', '\r', '.', ',' }, StringSplitOptions.RemoveEmptyEntries)
.Where(w => w.Length > 3)
.Distinct()
.ToList();
Expand Down
4 changes: 2 additions & 2 deletions src/Envoy.Core/Services/TemplateEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public async Task ExecuteTemplateAsync(
{
ct.ThrowIfCancellationRequested();

switch (step.Action.ToLower())
switch (step.Action.ToLowerInvariant())
{
case "wait_for":
await WaitForElementAsync(browser, step, ct);
Expand Down Expand Up @@ -186,7 +186,7 @@ private static string GetValueFromProfile(TailoredProfile profile, string field)
var data = profile.TailoredData;
var name = data.Name ?? "";
var nameParts = name.Split(' ', 2);
var key = (field ?? "").ToLower();
var key = (field ?? "").ToLowerInvariant();

switch (key)
{
Expand Down
4 changes: 2 additions & 2 deletions src/Envoy.Discovery/SeedBoards.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public static IReadOnlyList<AtsBoardRef> Load()
return Default;
}

public static readonly IReadOnlyList<AtsBoardRef> Default = new[]
public static readonly IReadOnlyList<AtsBoardRef> Default = Array.AsReadOnly(new[]
{
new AtsBoardRef { Ats = JobSource.Ashby, Token = "openai", CompanyName = "OpenAI" },
new AtsBoardRef { Ats = JobSource.Lever, Token = "matchgroup", CompanyName = "Match Group" },
new AtsBoardRef { Ats = JobSource.Lever, Token = "gopuff", CompanyName = "Gopuff" },
new AtsBoardRef { Ats = JobSource.Lever, Token = "veeva", CompanyName = "Veeva Systems" },
new AtsBoardRef { Ats = JobSource.Workable, Token = "viva", CompanyName = "Viva.com" },
};
});
}
2 changes: 1 addition & 1 deletion src/Envoy.GhostDetection/GhostScorer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public async Task<GhostScore> ScoreAsync(JobPosting posting, CancellationToken c
// ── TopEvidence: strongest lines, capped ─────────────────────────
var topEvidence = results
.OrderByDescending(r => r.Confidence * (r.Tier == SignalTier.Deterministic ? 10 : r.Tier == SignalTier.Probabilistic ? 3 : 1))
.SelectMany(r => r.Evidence)
.SelectMany(r => r.Evidence ?? Array.Empty<string>())
.Distinct()
.Take(6)
.ToArray();
Expand Down
4 changes: 0 additions & 4 deletions src/Envoy.GhostDetection/Signals/AtsCrossCheckSignal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ public AtsCrossCheckSignal(HttpClient http)
var segments = uri.Segments;
for (int i = 0; i < segments.Length - 1; i++)
{
if (segments[i].Trim('/').Equals("boards.greenhouse.io", StringComparison.OrdinalIgnoreCase))
continue;
if (segments[i].Trim('/').Equals("jobs", StringComparison.OrdinalIgnoreCase))
return null;
var seg = segments[i].Trim('/');
Expand All @@ -152,8 +150,6 @@ public AtsCrossCheckSignal(HttpClient http)
for (int i = 0; i < segments.Length; i++)
{
var seg = segments[i].Trim('/');
if (seg.Equals("jobs.lever.co", StringComparison.OrdinalIgnoreCase))
continue;
if (!string.IsNullOrEmpty(seg))
return seg;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Envoy.GhostDetection/Signals/PostingAgeSignal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class PostingAgeSignal : IGhostSignal

private static Seniority InferSeniority(string title)
{
var t = title.ToLowerInvariant();
var t = (title ?? string.Empty).ToLowerInvariant();

// Executive / very senior
if (ContainsAny(t, "vice president", "head of") ||
Expand Down
1 change: 1 addition & 0 deletions src/Envoy.UI/Theme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal static class Theme
public static readonly SolidColorBrush Muted = Freeze(new SolidColorBrush(Color.FromRgb(0x88, 0x92, 0xA4)));
public static readonly SolidColorBrush TextFg = Freeze(new SolidColorBrush(Color.FromRgb(0xE0, 0xE6, 0xF0)));
public static readonly SolidColorBrush Surface = Freeze(new SolidColorBrush(Color.FromRgb(0x11, 0x18, 0x27)));
public static readonly SolidColorBrush CardSurface = Freeze(new SolidColorBrush(Color.FromRgb(0x1A, 0x22, 0x35)));
public static readonly SolidColorBrush Background = Freeze(new SolidColorBrush(Color.FromRgb(0x0A, 0x0E, 0x17)));
public static readonly SolidColorBrush BorderColor = Freeze(new SolidColorBrush(Color.FromRgb(0x1A, 0x3A, 0x4A)));
public static readonly SolidColorBrush NavActiveBg = Freeze(new SolidColorBrush(Color.FromArgb(40, 0, 240, 255)));
Expand Down
6 changes: 3 additions & 3 deletions src/Envoy.UI/VaultView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ public async Task SetProfileId(Guid profileId)
{
var border = new Border
{
Background = new SolidColorBrush(Color.FromRgb(0x1A, 0x22, 0x35)),
Background = CardSurface,
CornerRadius = new CornerRadius(3),
BorderBrush = new SolidColorBrush(Color.FromRgb(0x1A, 0x3A, 0x4A)),
BorderBrush = BorderColor,
BorderThickness = new Thickness(1),
Padding = new Thickness(12),
Margin = new Thickness(0, 0, 0, 8),
Expand All @@ -83,7 +83,7 @@ public async Task SetProfileId(Guid profileId)
? string.Join("\n", _profile.Anomalies.Select(a => $"⚠ {a.Field}: {a.Message} [{a.Severity}]"))
: "✓ NO ANOMALIES DETECTED";
AnomaliesText.Foreground = _profile.Anomalies.Any()
? new SolidColorBrush(Color.FromRgb(0xFF, 0xE6, 0x00))
? Yellow
: Green;

SaveStatus.Text = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ public void AddEnvoyDiscovery_ResolvesServiceAndAllSources()
var discovery = provider.GetRequiredService<JobDiscoveryService>();
Assert.NotNull(discovery);

var sources = provider.GetServices<IAtsBoardSource>().ToList();
Assert.Equal(5, sources.Count);

var expected = new[] { JobSource.Greenhouse, JobSource.Lever, JobSource.Ashby, JobSource.Workable, JobSource.Recruitee };

var sources = provider.GetServices<IAtsBoardSource>().ToList();
Assert.Equal(expected.Length, sources.Count);
Assert.All(expected, ats => Assert.Contains(sources, s => s.Ats == ats));

var web = provider.GetRequiredService<IWebSearchSource>();
Assert.Equal("Brave Search", web.Name);

Assert.NotEmpty(discovery.DefaultBoards);
Assert.Equal(5, discovery.SupportedAts.Count);
Assert.Equal(expected.Length, discovery.SupportedAts.Count);
}
}