-
Notifications
You must be signed in to change notification settings - Fork 0
Strict-zero quality pass: codecov config + test duplication cleanup #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8a6df14
e2a6325
1c216de
40b4be3
4c76c30
a42b711
ec8b9db
c012656
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| version = 1 | ||
|
|
||
| # Keep this file explicit so provider-side analysis re-reads repo scope | ||
| # changes. Mirrors the conventions used across the Prekzursil fleet | ||
| # (env-inspector, Airline-Reservations-System, etc.). | ||
|
|
||
| exclude_patterns = [ | ||
| "**/bin/**", | ||
| "**/obj/**", | ||
| "**/TestResults/**", | ||
| "artifacts/**", | ||
| "publish/**", | ||
| "packaging/**", | ||
| "docs/**", | ||
| "fixtures/**", | ||
| "scripts/**", | ||
| "tests/**", | ||
| ] | ||
|
|
||
| test_patterns = [ | ||
| "tests/**", | ||
| "**/*.Tests/**", | ||
| "**/*Tests.cs", | ||
| ] | ||
|
|
||
| [[analyzers]] | ||
| name = "csharp" | ||
| enabled = true | ||
|
|
||
| [analyzers.meta] | ||
| # The .NET SDK pin lives in ``global.json`` (currently 8.0.x — see the | ||
| # ``sdk.version`` field, "8.0.419"). DeepSource accepts the dotted | ||
| # family identifier and resolves to the latest patch. | ||
| dotnet_version = "8.0" | ||
|
|
||
| [[analyzers]] | ||
| name = "secrets" | ||
| enabled = true | ||
|
|
||
| [[analyzers]] | ||
| name = "shell" | ||
| enabled = true | ||
|
|
||
| [[analyzers]] | ||
| name = "test-coverage" | ||
| enabled = true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # GuardRails configuration | ||
| # Reference: https://docs.guardrails.io/docs/configuration | ||
| # | ||
| # This config keeps GuardRails scanning enabled but bounds it to source | ||
| # code (excluding build output, generated artifacts, tests, and vendored | ||
| # fixtures) so its status check converges instead of timing out on the | ||
| # repository's full tree. All available analyzers are enabled in their | ||
| # default-rule configuration; we do not silence any rule — the goal is | ||
| # to make GuardRails finish a scan, not to make findings disappear. | ||
|
|
||
| version: 1 | ||
|
|
||
| ignore-paths: | ||
| - bin | ||
| - obj | ||
| - artifacts | ||
| - publish | ||
| - packaging | ||
| - docs | ||
| - fixtures | ||
| - TestResults | ||
| - "**/bin/**" | ||
| - "**/obj/**" | ||
| - "**/TestResults/**" | ||
| - "tests/**" | ||
| - "**/*.Tests/**" | ||
|
|
||
| # Engine pins follow GuardRails' "stable" channel; explicit so a silent | ||
| # upstream default change cannot regress the gate without a PR. | ||
| engines: | ||
| csharp: | ||
| enabled: true | ||
| secrets: | ||
| enabled: true | ||
| sast: | ||
| enabled: true | ||
| general: | ||
| secrets: | ||
| enabled: true | ||
| vulnerable_dependencies: | ||
| enabled: true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| codecov: | ||
| require_ci_to_pass: true | ||
|
|
||
| ignore: | ||
| - ".guardrails/**" | ||
| - ".deepsource.toml" | ||
| - ".qlty/**" | ||
| - ".github/dependabot.yml" | ||
|
|
||
| flags: | ||
| app: | ||
| paths: | ||
| - src/CodexSessionManager.App/ | ||
| core: | ||
| paths: | ||
| - src/CodexSessionManager.Core/ | ||
| storage: | ||
| paths: | ||
| - src/CodexSessionManager.Storage/ | ||
|
|
||
| coverage: | ||
| status: | ||
| project: | ||
| default: | ||
| target: 100.0% | ||
| threshold: 0% | ||
| patch: | ||
| default: | ||
| target: 100.0% | ||
| threshold: 0% |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,37 +8,19 @@ public sealed class MainWindowViewModelTests | |
| [Fact] | ||
| public async Task RefreshAsync_LoadsSessionsAndSelectsFirstSessionAsync() | ||
| { | ||
| var service = new FakeSessionBrowserService( | ||
| sessions: | ||
| [ | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| ]); | ||
| var service = new FakeSessionBrowserService(BuildTwoSessions()); | ||
|
|
||
| var viewModel = new MainWindowViewModel(service); | ||
|
|
||
| await viewModel.RefreshAsync(); | ||
|
|
||
| Assert.Equal("Ready", viewModel.StatusText); | ||
| Assert.Equal(2, viewModel.Sessions.Count); | ||
| Assert.Equal("session-1", viewModel.SelectedSession?.SessionId); | ||
| Assert.Contains("Readable transcript A", viewModel.TranscriptText, StringComparison.Ordinal); | ||
| AssertAllSessionsVisible(viewModel); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task ApplySearchAsync_UsesSearchHitsToFilterVisibleSessionsAsync() | ||
| { | ||
| var sessions = new[] | ||
| { | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| }; | ||
| var service = new FakeSessionBrowserService( | ||
| sessions, | ||
| searchHits: | ||
| [ | ||
| new SessionSearchHit("session-2", "Maintenance", @"C:\sessions\session-2.jsonl", "Maintenance snippet", 1) | ||
| ]); | ||
| var service = new FakeSessionBrowserService(BuildTwoSessions(), BuildMaintenanceHit()); | ||
|
|
||
| var viewModel = new MainWindowViewModel(service); | ||
| await viewModel.RefreshAsync(); | ||
|
|
@@ -53,64 +35,35 @@ public async Task ApplySearchAsync_UsesSearchHitsToFilterVisibleSessionsAsync() | |
| [Fact] | ||
| public async Task ApplySearchAsync_WithBlankQuery_RestoresAllSessionsAsync() | ||
| { | ||
| var sessions = new[] | ||
| { | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| }; | ||
| var service = new FakeSessionBrowserService( | ||
| sessions, | ||
| searchHits: | ||
| [ | ||
| new SessionSearchHit("session-2", "Maintenance", @"C:\sessions\session-2.jsonl", "Maintenance snippet", 1) | ||
| ]); | ||
| var service = new FakeSessionBrowserService(BuildTwoSessions(), BuildMaintenanceHit()); | ||
|
|
||
| var viewModel = new MainWindowViewModel(service); | ||
| await viewModel.RefreshAsync(); | ||
| await viewModel.ApplySearchAsync("maint"); | ||
|
|
||
| await viewModel.ApplySearchAsync(" "); | ||
|
|
||
| Assert.Equal(2, viewModel.Sessions.Count); | ||
| Assert.Equal("session-1", viewModel.SelectedSession?.SessionId); | ||
| Assert.Contains("Readable transcript A", viewModel.TranscriptText, StringComparison.Ordinal); | ||
| AssertAllSessionsVisible(viewModel); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task ApplySearchAsync_WithNullQuery_RestoresAllSessionsAsync() | ||
| { | ||
| var sessions = new[] | ||
| { | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| }; | ||
| var service = new FakeSessionBrowserService( | ||
| sessions, | ||
| searchHits: | ||
| [ | ||
| new SessionSearchHit("session-2", "Maintenance", @"C:\sessions\session-2.jsonl", "Maintenance snippet", 1) | ||
| ]); | ||
| var service = new FakeSessionBrowserService(BuildTwoSessions(), BuildMaintenanceHit()); | ||
|
|
||
| var viewModel = new MainWindowViewModel(service); | ||
| await viewModel.RefreshAsync(); | ||
| await viewModel.ApplySearchAsync("maint"); | ||
|
|
||
| await viewModel.ApplySearchAsync(null!); | ||
|
|
||
| Assert.Equal(2, viewModel.Sessions.Count); | ||
| Assert.Equal("session-1", viewModel.SelectedSession?.SessionId); | ||
| Assert.Contains("Readable transcript A", viewModel.TranscriptText, StringComparison.Ordinal); | ||
| AssertAllSessionsVisible(viewModel); | ||
| } | ||
|
|
||
| [Fact] | ||
| public async Task ApplySearchAsync_WithNoHits_clears_selection_and_transcriptAsync() | ||
| { | ||
| var sessions = new[] | ||
| { | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| }; | ||
| var service = new FakeSessionBrowserService(sessions, searchHits: []); | ||
| var service = new FakeSessionBrowserService(BuildTwoSessions(), searchHits: []); | ||
|
|
||
| var viewModel = new MainWindowViewModel(service); | ||
| await viewModel.RefreshAsync(); | ||
|
|
@@ -125,18 +78,29 @@ public async Task ApplySearchAsync_WithNoHits_clears_selection_and_transcriptAsy | |
| [Fact] | ||
| public async Task ApplySearchAsync_single_parameter_overload_normalizes_null_queryAsync() | ||
| { | ||
| var sessions = new[] | ||
| { | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| }; | ||
| var service = new FakeSessionBrowserService(sessions, searchHits: []); | ||
| var service = new FakeSessionBrowserService(BuildTwoSessions(), searchHits: []); | ||
|
|
||
| var viewModel = new MainWindowViewModel(service); | ||
| await viewModel.RefreshAsync(); | ||
|
|
||
| await viewModel.ApplySearchAsync(null!); | ||
|
|
||
| AssertAllSessionsVisible(viewModel); | ||
| } | ||
|
|
||
| private static IndexedLogicalSession[] BuildTwoSessions() => | ||
| [ | ||
| BuildSession("session-1", "Renderer work", "Readable transcript A"), | ||
| BuildSession("session-2", "Maintenance", "Readable transcript B") | ||
| ]; | ||
|
|
||
| private static SessionSearchHit[] BuildMaintenanceHit() => | ||
| [ | ||
| new SessionSearchHit("session-2", "Maintenance", @"C:\sessions\session-2.jsonl", "Maintenance snippet", 1) | ||
| ]; | ||
|
|
||
| private static void AssertAllSessionsVisible(MainWindowViewModel viewModel) | ||
| { | ||
| Assert.Equal(2, viewModel.Sessions.Count); | ||
| Assert.Equal("session-1", viewModel.SelectedSession?.SessionId); | ||
| Assert.Contains("Readable transcript A", viewModel.TranscriptText, StringComparison.Ordinal); | ||
|
Comment on lines
+102
to
106
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The refactoring dropped the [Bug] |
||
|
|
@@ -146,11 +110,8 @@ private static IndexedLogicalSession BuildSession(string sessionId, string threa | |
| new( | ||
| SessionId: sessionId, | ||
| ThreadName: threadName, | ||
| PreferredCopy: new SessionPhysicalCopy(sessionId, $@"C:\Users\Prekzursil\.codex\sessions\{sessionId}.jsonl", SessionStoreKind.Live, new SessionPhysicalCopyState(DateTimeOffset.UtcNow, 1024, false)), | ||
| PhysicalCopies: | ||
| [ | ||
| new SessionPhysicalCopy(sessionId, $@"C:\Users\Prekzursil\.codex\sessions\{sessionId}.jsonl", SessionStoreKind.Live, new SessionPhysicalCopyState(DateTimeOffset.UtcNow, 1024, false)) | ||
| ], | ||
| PreferredCopy: BuildCopy(sessionId), | ||
| PhysicalCopies: [BuildCopy(sessionId)], | ||
| SearchDocument: new SessionSearchDocument | ||
| { | ||
| ReadableTranscript = transcript, | ||
|
|
@@ -165,6 +126,13 @@ private static IndexedLogicalSession BuildSession(string sessionId, string threa | |
| Notes = string.Empty | ||
| }); | ||
|
|
||
| private static SessionPhysicalCopy BuildCopy(string sessionId) => | ||
| new( | ||
| sessionId, | ||
| $@"C:\Users\Prekzursil\.codex\sessions\{sessionId}.jsonl", | ||
| SessionStoreKind.Live, | ||
| new SessionPhysicalCopyState(DateTimeOffset.UtcNow, 1024, false)); | ||
|
|
||
| private sealed class FakeSessionBrowserService : CodexSessionManager.App.ViewModels.ISessionBrowserService | ||
| { | ||
| private readonly IReadOnlyList<IndexedLogicalSession> _sessions; | ||
|
|
@@ -198,4 +166,3 @@ public Task RefreshIndexAsync(CancellationToken cancellationToken) | |
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Re-add a
StatusTextassertion in this test. After the helper extraction, this path no longer verifies the expected ready-state text, so a regression there would go undetected.Prompt for AI agents