Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0de6cef76d | |||
| 3012965404 | |||
| 9c9fe48d5f | |||
| bfbfaeb903 | |||
| 86c589a0e0 | |||
| 70ddee8d3d | |||
| b6ee418c7a | |||
| b8292f6f72 | |||
| 6bfdbd9db7 | |||
| bca750446f | |||
| 327d99dfda | |||
| 171a69089f |
@@ -1,4 +1,5 @@
|
||||
using System.Security.Claims;
|
||||
using System.Data.Common;
|
||||
using JobTrackerApi.Controllers;
|
||||
using JobTrackerApi.Data;
|
||||
using JobTrackerApi.Models;
|
||||
@@ -8,6 +9,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
@@ -16,6 +18,78 @@ namespace JobTrackerApi.Tests;
|
||||
// Real SQLite: EF InMemory cannot prove LIKE, relational ordering or tenant joins.
|
||||
public sealed class JobQueryParityTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(250)]
|
||||
[InlineData(2500)]
|
||||
public async Task Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(int size)
|
||||
{
|
||||
await using var connection = new SqliteConnection("Data Source=:memory:");
|
||||
await connection.OpenAsync();
|
||||
var aggregate = new CorrespondenceAggregateRecorder();
|
||||
var options = new DbContextOptionsBuilder<JobTrackerContext>().UseSqlite(connection).AddInterceptors(aggregate).Options;
|
||||
var user = new Mock<ICurrentUserService>();
|
||||
user.SetupGet(x => x.UserId).Returns("owner");
|
||||
await using var db = new JobTrackerContext(options, user.Object);
|
||||
await db.Database.EnsureCreatedAsync();
|
||||
db.Users.AddRange(new ApplicationUser { Id = "owner", UserName = "owner" }, new ApplicationUser { Id = "other", UserName = "other" });
|
||||
var company = new Company { Name = "Synthetic", OwnerUserId = "owner" };
|
||||
var jobs = Enumerable.Range(0, size).Select(i => new JobApplication
|
||||
{
|
||||
Company = company, OwnerUserId = "owner", JobTitle = $"Application {i:D4}", Status = "Applied",
|
||||
DateApplied = new DateTime(2026, 10, 1),
|
||||
}).ToList();
|
||||
db.JobApplications.AddRange(jobs);
|
||||
await db.SaveChangesAsync();
|
||||
db.Correspondences.AddRange(jobs.Select(job => new Correspondence
|
||||
{
|
||||
JobApplicationId = job.Id, Content = "Synthetic mail", From = "Company", Date = new DateTime(2026, 10, 2),
|
||||
}));
|
||||
await db.SaveChangesAsync();
|
||||
user.SetupGet(x => x.UserId).Returns("other");
|
||||
var foreign = new JobApplication { Company = new Company { Name = "Foreign", OwnerUserId = "other" }, OwnerUserId = "other", JobTitle = "Foreign", Status = "Applied" };
|
||||
db.JobApplications.Add(foreign);
|
||||
await db.SaveChangesAsync();
|
||||
db.Correspondences.Add(new Correspondence { JobApplicationId = foreign.Id, Content = "Foreign mail", From = "Company", Date = new DateTime(2026, 10, 3) });
|
||||
await db.SaveChangesAsync();
|
||||
user.SetupGet(x => x.UserId).Returns("owner");
|
||||
var controller = new JobApplicationsController(db, Mock.Of<ISummarizerService>(), TestHostFactory.CreateUserManager().Object)
|
||||
{
|
||||
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal(new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, "owner")], "test")) } }
|
||||
};
|
||||
|
||||
var result = await controller.GetAll(page: 2, pageSize: 15, sortBy: "jobTitle", sortDir: "asc");
|
||||
var page = Assert.IsType<PagedResult<JobApplicationDto>>(Assert.IsType<OkObjectResult>(result.Result).Value);
|
||||
Assert.Equal(size, page.Total);
|
||||
var expected = jobs.Skip(15).Take(15).Select(job => job.Id).ToArray();
|
||||
Assert.Equal(expected, page.Items.Select(job => job.Id));
|
||||
var (sql, parameters) = Assert.Single(aggregate.Commands);
|
||||
await using var replay = connection.CreateCommand();
|
||||
replay.CommandText = sql;
|
||||
foreach (var parameter in parameters) replay.Parameters.AddWithValue(parameter.Key, parameter.Value ?? DBNull.Value);
|
||||
var materialised = new List<int>();
|
||||
await using (var reader = await replay.ExecuteReaderAsync())
|
||||
while (await reader.ReadAsync()) materialised.Add(reader.GetInt32(0));
|
||||
Assert.Equal(15, materialised.Count);
|
||||
Assert.Equal(expected.Order(), materialised.Order());
|
||||
|
||||
aggregate.Commands.Clear();
|
||||
await controller.GetBoard();
|
||||
await controller.GetAll(q: "absent");
|
||||
Assert.Empty(aggregate.Commands);
|
||||
}
|
||||
|
||||
private sealed class CorrespondenceAggregateRecorder : DbCommandInterceptor
|
||||
{
|
||||
public List<(string Sql, Dictionary<string, object?> Parameters)> Commands { get; } = [];
|
||||
|
||||
public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (command.CommandText.Contains("MAX(", StringComparison.OrdinalIgnoreCase) && command.CommandText.Contains("\"Correspondences\"", StringComparison.Ordinal))
|
||||
Commands.Add((command.CommandText, command.Parameters.Cast<DbParameter>().ToDictionary(p => p.ParameterName, p => p.Value)));
|
||||
return ValueTask.FromResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("all")]
|
||||
[InlineData("search")]
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
using JobTrackerApi.Controllers;
|
||||
using JobTrackerApi.Data;
|
||||
using JobTrackerApi.Models;
|
||||
using JobTrackerApi.Services;
|
||||
using JobTrackerApi.Tests.TestSupport;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace JobTrackerApi.Tests;
|
||||
|
||||
public sealed class RuleSettingsFreshnessTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("list")]
|
||||
[InlineData("board")]
|
||||
[InlineData("detail")]
|
||||
[InlineData("reminders")]
|
||||
[InlineData("readiness")]
|
||||
public async Task Saved_owner_thresholds_are_visible_on_the_next_read(string surface)
|
||||
{
|
||||
await using var fixture = await Fixture.CreateAsync();
|
||||
await using var read = fixture.Context("owner-a");
|
||||
var controller = fixture.Controller(read);
|
||||
Assert.False(await FollowUp(controller, fixture.JobA, surface));
|
||||
await using (var write = fixture.Context("owner-a"))
|
||||
Assert.IsType<NoContentResult>(await new RulesController(write).Update(Settings(1), default));
|
||||
// Reuse the reader after the committed write: tracked entities must not mask persistence.
|
||||
Assert.True(await FollowUp(controller, fixture.JobA, surface));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Saving_owner_a_preserves_owner_b_and_existing_readers_see_subsequent_writes()
|
||||
{
|
||||
await using var fixture = await Fixture.CreateAsync();
|
||||
await using var a = fixture.Context("owner-a");
|
||||
await using var b = fixture.Context("owner-b");
|
||||
var ca = fixture.Controller(a);
|
||||
var cb = fixture.Controller(b);
|
||||
Assert.False(await FollowUp(ca, fixture.JobA, "list"));
|
||||
Assert.False(await FollowUp(cb, fixture.JobB, "list"));
|
||||
await using (var write = fixture.Context("owner-a"))
|
||||
await new RulesController(write).Update(Settings(1), default);
|
||||
Assert.True(await FollowUp(ca, fixture.JobA, "list"));
|
||||
Assert.False(await FollowUp(cb, fixture.JobB, "list"));
|
||||
// A later write in the opposite direction must also be visible through both old/new controllers.
|
||||
await using (var write = fixture.Context("owner-a"))
|
||||
await new RulesController(write).Update(Settings(30), default);
|
||||
await using var fresh = fixture.Context("owner-a");
|
||||
Assert.False(await FollowUp(fixture.Controller(fresh), fixture.JobA, "list"));
|
||||
Assert.False(await FollowUp(ca, fixture.JobA, "list"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Completing_an_older_request_cannot_restore_old_rules_after_a_save()
|
||||
{
|
||||
await using var fixture = await Fixture.CreateAsync();
|
||||
await using var oldRead = fixture.Context("owner-a");
|
||||
var reached = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var release = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var users = TestHostFactory.CreateUserManager();
|
||||
users.Setup(x => x.FindByIdAsync("owner-a")).Returns(async () =>
|
||||
{
|
||||
// GetById has already loaded/evaluated the old rules; no model is called.
|
||||
reached.TrySetResult(true);
|
||||
await release.Task;
|
||||
return (ApplicationUser?)null;
|
||||
});
|
||||
var older = new JobApplicationsController(oldRead, Mock.Of<ISummarizerService>(), users.Object)
|
||||
{
|
||||
ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext
|
||||
{
|
||||
User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "owner-a") }, "test")),
|
||||
} },
|
||||
};
|
||||
var pending = FollowUp(older, fixture.JobA, "detail");
|
||||
try
|
||||
{
|
||||
await reached.Task.WaitAsync(TimeSpan.FromSeconds(10));
|
||||
await using (var write = fixture.Context("owner-a"))
|
||||
await new RulesController(write).Update(Settings(1), default);
|
||||
await using var freshRead = fixture.Context("owner-a");
|
||||
var fresh = fixture.Controller(freshRead);
|
||||
Assert.True(await FollowUp(fresh, fixture.JobA, "list"));
|
||||
release.TrySetResult(true);
|
||||
Assert.False(await pending); // A request begun before the save may return its earlier snapshot.
|
||||
Assert.True(await FollowUp(fresh, fixture.JobA, "list"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
release.TrySetResult(true);
|
||||
await pending;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Global_save_refreshes_fallback_but_preserves_explicit_owner_override()
|
||||
{
|
||||
await using var fixture = await Fixture.CreateAsync();
|
||||
await using (var setup = fixture.Context("owner-a"))
|
||||
{
|
||||
setup.UserRuleSettings.Remove(await setup.UserRuleSettings.SingleAsync());
|
||||
await setup.SaveChangesAsync();
|
||||
}
|
||||
await using var fallback = fixture.Context("owner-a");
|
||||
await using var overridden = fixture.Context("owner-b");
|
||||
var ca = fixture.Controller(fallback);
|
||||
var cb = fixture.Controller(overridden);
|
||||
Assert.False(await FollowUp(ca, fixture.JobA, "list"));
|
||||
Assert.False(await FollowUp(cb, fixture.JobB, "list"));
|
||||
await using (var global = fixture.Context(null))
|
||||
Assert.IsType<NoContentResult>(await new RulesController(global).Update(Settings(1), default));
|
||||
Assert.True(await FollowUp(ca, fixture.JobA, "list"));
|
||||
Assert.False(await FollowUp(cb, fixture.JobB, "list"));
|
||||
}
|
||||
|
||||
private static RuleSettings Settings(int followUp) => new()
|
||||
{
|
||||
AppliedFollowUpDays = followUp, AppliedGhostDays = 365,
|
||||
OfferFollowUpDays = 30, OfferGhostDays = 365,
|
||||
FeedbackFollowUpDays = 30, FeedbackGhostDays = 365,
|
||||
};
|
||||
|
||||
private static async Task<bool> FollowUp(JobApplicationsController controller, int id, string surface)
|
||||
{
|
||||
if (surface == "readiness")
|
||||
{
|
||||
var result = await controller.GetReadiness(id, default);
|
||||
return Assert.IsType<ReadinessDto>(Assert.IsType<OkObjectResult>(result.Result).Value).WorkflowSignal.NeedsFollowUpAction;
|
||||
}
|
||||
if (surface == "detail")
|
||||
{
|
||||
var result = await controller.GetById(id, default);
|
||||
return Assert.IsType<JobApplicationDto>(Assert.IsType<OkObjectResult>(result.Result).Value).NeedsFollowUp;
|
||||
}
|
||||
if (surface == "list")
|
||||
{
|
||||
var result = await controller.GetAll();
|
||||
return Assert.Single(Assert.IsType<PagedResult<JobApplicationDto>>(Assert.IsType<OkObjectResult>(result.Result).Value).Items).NeedsFollowUp;
|
||||
}
|
||||
if (surface == "board")
|
||||
{
|
||||
var result = await controller.GetBoard(needsFollowUp: true);
|
||||
return Assert.IsType<List<JobApplication>>(Assert.IsType<OkObjectResult>(result.Result).Value).Any(job => job.Id == id);
|
||||
}
|
||||
var response = await controller.GetReminders();
|
||||
var jobs = Assert.IsType<List<JobApplicationDto>>(Assert.IsType<OkObjectResult>(response.Result).Value);
|
||||
return jobs.SingleOrDefault(job => job.Id == id)?.NeedsFollowUp ?? false;
|
||||
}
|
||||
|
||||
private sealed class Fixture : IAsyncDisposable
|
||||
{
|
||||
private readonly SqliteConnection _connection = new("Data Source=:memory:");
|
||||
public int JobA { get; private set; }
|
||||
public int JobB { get; private set; }
|
||||
|
||||
public JobTrackerContext Context(string? owner)
|
||||
{
|
||||
var user = new Mock<ICurrentUserService>();
|
||||
user.SetupGet(x => x.UserId).Returns(owner);
|
||||
return new JobTrackerContext(new DbContextOptionsBuilder<JobTrackerContext>().UseSqlite(_connection).Options, user.Object);
|
||||
}
|
||||
|
||||
public JobApplicationsController Controller(JobTrackerContext db) =>
|
||||
new(db, Mock.Of<ISummarizerService>(), TestHostFactory.CreateUserManager().Object);
|
||||
|
||||
public static async Task<Fixture> CreateAsync()
|
||||
{
|
||||
var fixture = new Fixture();
|
||||
await fixture._connection.OpenAsync();
|
||||
await using var db = fixture.Context("owner-a");
|
||||
await db.Database.EnsureCreatedAsync();
|
||||
db.Users.AddRange(new ApplicationUser { Id = "owner-a", UserName = "owner-a" }, new ApplicationUser { Id = "owner-b", UserName = "owner-b" });
|
||||
var global = await db.RuleSettings.SingleAsync();
|
||||
global.AppliedFollowUpDays = 30;
|
||||
global.AppliedGhostDays = 365;
|
||||
foreach (var owner in new[] { "owner-a", "owner-b" })
|
||||
{
|
||||
await using var owned = fixture.Context(owner);
|
||||
owned.UserRuleSettings.Add(new UserRuleSettings { OwnerUserId = owner, AppliedFollowUpDays = 30, AppliedGhostDays = 365 });
|
||||
// Complete package avoids unrelated package-gap reminders masking the rule decision.
|
||||
var job = new JobApplication
|
||||
{
|
||||
OwnerUserId = owner, Company = new Company { Name = owner, OwnerUserId = owner },
|
||||
JobTitle = "Synthetic engineer", Status = "Applied", DateApplied = DateTime.Now.AddDays(-10), FollowUpAt = DateTime.Now.AddDays(100),
|
||||
TailoredCvText = "Synthetic CV", Notes = "<<<APPLICATION_ANSWER_DRAFT>>>\nSynthetic answer\n<<<END_APPLICATION_ANSWER_DRAFT>>>",
|
||||
};
|
||||
owned.JobApplications.Add(job);
|
||||
// Users must exist before owner-scoped rows are inserted.
|
||||
await db.SaveChangesAsync();
|
||||
await owned.SaveChangesAsync();
|
||||
if (owner == "owner-a") fixture.JobA = job.Id; else fixture.JobB = job.Id;
|
||||
}
|
||||
return fixture;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _connection.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using JobTrackerApi.Data;
|
||||
using JobTrackerApi.Models;
|
||||
using JobTrackerApi.Services;
|
||||
@@ -31,10 +30,9 @@ namespace JobTrackerApi.Controllers
|
||||
private readonly ICvTemplateRenderer _cvTemplateRenderer;
|
||||
private readonly ICvPdfExporter _cvPdfExporter;
|
||||
private readonly IJobCvMatchService _matchService;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IApplicationChecklistService _checklist;
|
||||
|
||||
public JobApplicationsController(JobTrackerContext db, ISummarizerService summarizer, UserManager<ApplicationUser> users, ICvTemplateRenderer? cvTemplateRenderer = null, ICvPdfExporter? cvPdfExporter = null, IJobCvMatchService? matchService = null, IMemoryCache? cache = null, IApplicationChecklistService? checklist = null)
|
||||
public JobApplicationsController(JobTrackerContext db, ISummarizerService summarizer, UserManager<ApplicationUser> users, ICvTemplateRenderer? cvTemplateRenderer = null, ICvPdfExporter? cvPdfExporter = null, IJobCvMatchService? matchService = null, IApplicationChecklistService? checklist = null)
|
||||
{
|
||||
_checklist = checklist ?? new ApplicationChecklistService(db);
|
||||
_db = db;
|
||||
@@ -43,21 +41,6 @@ namespace JobTrackerApi.Controllers
|
||||
_cvTemplateRenderer = cvTemplateRenderer ?? new CvTemplateRenderer();
|
||||
_cvPdfExporter = cvPdfExporter ?? new ThrowingCvPdfExporter();
|
||||
_matchService = matchService ?? new JobCvMatchService();
|
||||
_cache = cache ?? new MemoryCache(new MemoryCacheOptions());
|
||||
}
|
||||
|
||||
// ponytail: RulesEngine.GetSettings is per-user (falls back to the global RuleSettings
|
||||
// singleton only when the user has no override), so the cache key must include the
|
||||
// current user id -- a single global key would leak one user's follow-up rules to another.
|
||||
private async Task<RuleSettings> GetCachedRuleSettingsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheKey = $"rulesettings:{_db.CurrentUserId ?? "anon"}";
|
||||
var cached = await _cache.GetOrCreateAsync(cacheKey, async entry =>
|
||||
{
|
||||
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30);
|
||||
return await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
});
|
||||
return cached!;
|
||||
}
|
||||
|
||||
private sealed class ThrowingCvPdfExporter : ICvPdfExporter
|
||||
@@ -539,11 +522,10 @@ Canonical profile:
|
||||
query = query.Where(j => j.Location != null && EF.Functions.Like(j.Location, like));
|
||||
}
|
||||
|
||||
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
|
||||
var settings = await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
var now = DateTime.Now;
|
||||
|
||||
var lastMsg = await _db.Correspondences
|
||||
.AsNoTracking()
|
||||
Task<Dictionary<int, DateTime?>> LoadLatestMessagesAsync(IQueryable<Correspondence> messages) => messages
|
||||
.GroupBy(c => c.JobApplicationId)
|
||||
.Select(g => new { JobApplicationId = g.Key, Last = g.Max(x => x.Date) })
|
||||
.ToDictionaryAsync(x => x.JobApplicationId, x => (DateTime?)x.Last, cancellationToken);
|
||||
@@ -556,11 +538,12 @@ Canonical profile:
|
||||
{
|
||||
// Both filters depend on rule evaluation and workflow signals that include normalized
|
||||
// note content, so evaluate before pagination to keep totals/pages correct.
|
||||
var latestMessages = await LoadLatestMessagesAsync(_db.Correspondences.AsNoTracking());
|
||||
var pre = await query.ToListAsync(cancellationToken);
|
||||
var filtered = new List<JobApplication>();
|
||||
foreach (var j in pre)
|
||||
{
|
||||
lastMsg.TryGetValue(j.Id, out var lm);
|
||||
latestMessages.TryGetValue(j.Id, out var lm);
|
||||
var d = RulesEngine.Evaluate(settings, j, now, lm);
|
||||
var signal = BuildWorkflowSignal(j, d);
|
||||
var matchesFollowUp = !needsFollowUp || d.NeedsFollowUp;
|
||||
@@ -592,7 +575,7 @@ Canonical profile:
|
||||
var dtoItems = new List<JobApplicationDto>();
|
||||
foreach (var j in pageItems)
|
||||
{
|
||||
lastMsg.TryGetValue(j.Id, out var lm);
|
||||
latestMessages.TryGetValue(j.Id, out var lm);
|
||||
var d = RulesEngine.Evaluate(settings, j, now, lm);
|
||||
dtoItems.Add(BuildJobApplicationDto(j, d));
|
||||
}
|
||||
@@ -623,6 +606,12 @@ Canonical profile:
|
||||
.Take(pageSize)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
if (items.Count == 0) return Ok(new PagedResult<JobApplicationDto>([], total, page, pageSize));
|
||||
|
||||
var pageIds = items.Select(job => job.Id).ToArray();
|
||||
var lastMsg = await LoadLatestMessagesAsync(_db.Correspondences.AsNoTracking()
|
||||
.Where(message => pageIds.Contains(message.JobApplicationId)));
|
||||
|
||||
var dtos = new List<JobApplicationDto>();
|
||||
foreach (var j in items)
|
||||
{
|
||||
@@ -644,7 +633,7 @@ Canonical profile:
|
||||
|
||||
if (job is null) return NotFound();
|
||||
|
||||
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
|
||||
var settings = await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
var now = DateTime.Now;
|
||||
var lm = await _db.Correspondences
|
||||
.AsNoTracking()
|
||||
@@ -687,7 +676,7 @@ Canonical profile:
|
||||
if (upcomingDays < 1) upcomingDays = 1;
|
||||
if (upcomingDays > 90) upcomingDays = 90;
|
||||
|
||||
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
|
||||
var settings = await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
var now = DateTime.Now;
|
||||
var upcomingTo = now.AddDays(upcomingDays);
|
||||
|
||||
@@ -833,7 +822,7 @@ Canonical profile:
|
||||
.Include(j => j.Company)
|
||||
.FirstAsync(j => j.Id == job.Id, cancellationToken);
|
||||
|
||||
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
|
||||
var settings = await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
var followUp = RulesEngine.Evaluate(settings, created, DateTime.Now, lastMessageAt: null);
|
||||
return CreatedAtAction(nameof(GetById), new { id = created.Id }, BuildJobApplicationDto(created, followUp));
|
||||
}
|
||||
@@ -1023,7 +1012,7 @@ Canonical profile:
|
||||
|
||||
await _db.SaveChangesAsync(cancellationToken);
|
||||
|
||||
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
|
||||
var settings = await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
var lastMsg = await _db.Correspondences
|
||||
.AsNoTracking()
|
||||
.Where(c => c.JobApplicationId == id)
|
||||
@@ -1377,7 +1366,7 @@ Candidate CV/profile:
|
||||
.FirstOrDefaultAsync(j => j.Id == id, cancellationToken);
|
||||
if (job is null) return NotFound();
|
||||
|
||||
var settings = await GetCachedRuleSettingsAsync(cancellationToken);
|
||||
var settings = await RulesEngine.GetSettings(_db, cancellationToken);
|
||||
var now = DateTime.Now;
|
||||
var lastMessageAt = await _db.Correspondences
|
||||
.AsNoTracking()
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# A3 Jobs performance integration
|
||||
|
||||
Base `6bfdbd9db72e06f18f8aa9aaf57b025bff55ce5b` on `codex/a3-ui-10`. Commit `b8292f6f7299daa704bbe41efa8081660c2b6e27` integrates the relevant deltas from isolated `af33e455` and `97d06180`. The salary call and read configuration were reapplied at their current A3 locations because the older JobTable context had changed. The current selection, filters, board and Trash implementations stay in place.
|
||||
|
||||
The mobile salary display uses the selected EN/NB number format and established period labels. Original text and unknown imported periods remain displayable. Jobs and Trash update existing error copy with the language without fetching the same page again. Retry continues to fetch the current query.
|
||||
|
||||
The deferred JobTable trial passed 96 selected tests across nine suites, full lint and the static export build with TypeScript. The first run had one obsolete Landing test selector for “Norsk”. The existing accessible name is “Norsk bokmål”. Only the test selector was updated. The first failure and green receipts are retained.
|
||||
|
||||
The comparison uses Chromium 151, cold isolated contexts, local static exports, blocked external requests, and a synthetic 15-application response. The separate desktop and emulated mobile profiles use fixed network and CPU settings. Public routes must request zero private application rows. Each cold Jobs load must request exactly one page. Gzip sizes are estimates at level 6, and route marker timings include browser polling. These are not production timings or field Web Vitals.
|
||||
|
||||
## Deferred JobTable trial held from A3
|
||||
|
||||
The temporary candidate used `b8292f6f` and the isolated App import change from `85ebbd9f`, with trial App blob `f98ce042fd36e0b5880aa6108c6d601a3976820f`. The baseline export was built from `6bfdbd9d`. [Paired data](evidence/a3-jobs/PAIRED.json) has three cold repeats per route, build and profile. Order alternated. A local graph index refresh briefly overlapped the experiment. Desktop used 40 ms / 10 Mbps / CPU 1×. The 390 px phone profile used 150 ms / 1.6 Mbps / CPU 4×.
|
||||
|
||||
| Route | Raw JS before → trial | Desktop median marker | Phone median marker |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Landing | 2,024,172 → 1,782,542 B | 2,445 → 1,921 ms | 12,124 → 11,445 ms |
|
||||
| Login | 2,024,172 → 1,782,542 B | 2,448 → 1,924 ms | 11,997 → 10,789 ms |
|
||||
| Jobs | 2,052,915 → 2,082,356 B | 2,433 → 2,440 ms | 13,314 → 13,773 ms |
|
||||
|
||||
The trial saves 241,630 raw JS bytes and 71,651 estimated gzip bytes on each public route. Jobs adds 29,441 raw bytes. The slow phone profile showed a 459 ms median first-row delay with all three candidate samples later than the baseline samples. Retain the eager JobTable import in A3. The isolated experiment remains available for a revised loading strategy that protects the Jobs marker.
|
||||
|
||||
## Published source checks
|
||||
|
||||
The final eager source at `b6ee418c7a93f1fe3dcdb687b26fd4cf8a489587` also integrates the isolated `4c12f769` Admin System metric change. It uses the current locale for database size and CV benchmark percentages, preserving status freshness and existing controls. No benchmark or diagnostic action was invoked. The final 55 tests across Admin System, JobTable and Jobs integration, full lint and static export with TypeScript passed. These tests overlap the trial run and are reported separately.
|
||||
|
||||
A focused [browser check](evidence/a3-jobs/LOCALE.json) dispatched an English-to-Bokmål storage event after the Jobs row was visible. The extra paged GET count fell from one to zero on desktop and emulated phone, with one initial GET on each build. The row remained visible, the document language changed and no write was attempted. One fresh context per build and profile. This check qualifies the cross-tab language change without saving preferences to a live account.
|
||||
@@ -0,0 +1,11 @@
|
||||
# PERF-01 Companies cache
|
||||
|
||||
Base `fd524a4b9d55d671d4f9c93134057d42f9cd6373`. The browser's Companies cache is scoped to the current owner. A response that started before invalidation could finish after its replacement and overwrite the fresh list. A pre-logout response could also write after signing back in as the same account. Separately, a mounting consumer could publish its initial empty array as cached data before the network request finished, so another consumer could miss the shared result.
|
||||
|
||||
Only the current in-flight response can now populate the cache. It must still match the active owner. The resource-state effect no longer writes a second copy into the shared cache. Existing readers, invalidation callers, request URL and server authorisation are unchanged.
|
||||
|
||||
Before the fix, the three added cases failed on the stale post-edit list, a missed shared response and the stale pre-logout list. After the fix, the two simultaneous readers both received the shared result with exactly one request. The post-invalidation check used exactly two requests across the old and new generations, with no extra request on a warm mount. Re-login and account switching checks also passed.
|
||||
|
||||
**Verification:** 16 tests across the account-scoped state, Edit Job revision and theme state suites passed. Targeted lint and TypeScript passed. The test worktree reused the installed dependency tree from the matching A3 lockfile. These are mock request counts, with no browser or production latency measurement.
|
||||
|
||||
The A3 integration used the exact source and regression delta from `21db35d2b965fbda2ddf5b419ac2646fcae05517`. Both input files matched its parent at A3 base `bca750446f1069eb55d648be838be192d70c2d30`. The fresh A3 run passed 37 tests across account-scoped state, JobTable density and Jobs integration, plus type-check and scoped lint. These runs overlap. [A3 receipt](../ui-modernisation/evidence/perf-company-cache/TESTS.txt)
|
||||
@@ -0,0 +1,25 @@
|
||||
# PERF-01 Rules settings freshness
|
||||
|
||||
Source baseline: `9c9fe48d5f321c653049f09ced5b7e27701fe2a8`; isolated branch `codex/perf-rules-freshness`.
|
||||
|
||||
Successful Rules settings saves previously left the API's owner-keyed 30-second cache unchanged. Settings could therefore display the saved values while Applications, Board filtering, details, reminders and readiness continued using old thresholds. Invalidating only the owner's entry would also miss global-fallback dependencies and permit an older asynchronous cache fill to repopulate stale data.
|
||||
|
||||
The job controller now reads through the existing `RulesEngine.GetSettings` owner/fallback implementation on each request. There is no rules cache to repopulate, including across separate API processes. Existing database/query-filter contracts and global `AddMemoryCache` remain unchanged. The unused optional constructor cache argument is removed; the following optional checklist argument retains its name and all existing callers compile. Create and AI-refresh responses share the same corrected settings read; neither endpoint is activated by these tests.
|
||||
|
||||
The cost is one owner-primary-key settings lookup per job request, plus a singleton lookup when no override exists. This correctness fix is not a measured latency or throughput improvement. No distributed invalidation infrastructure was introduced. A read begun before a committed update may return its earlier snapshot; a completed older response cannot cache that snapshot for later requests.
|
||||
|
||||
## Verification
|
||||
|
||||
- **RED:** Seven real SQLite cases with a shared `MemoryCache` failed before the application change, all with expected `True` / actual `False` at the post-save freshness assertion. These cover list, Board follow-up filtering, detail, reminders, readiness, owner isolation and global fallback. Local receipt: `JobTrackerApi.Tests/TestResults/rules-red.trx`.
|
||||
- **PASSED:** The final focused regression run passed **35 distinct tests**, including eight new freshness cases, plus query parity, workflow signals, prospect rules and concurrent initialization. The eighth case pauses an older detail request at a mock identity lookup after rule evaluation, saves new rules, verifies a fresh request, completes the older response and verifies another fresh read. This uses no model or provider. Local receipt: `JobTrackerApi.Tests/TestResults/rules-regression.trx`.
|
||||
- **PASSED:** `dotnet build "Job tracker.sln" --no-restore --verbosity quiet`: zero warnings/errors.
|
||||
- **PASSED:** `git diff --check`.
|
||||
- **PASSED:** `graphify update .` rebuilt the local AST graph without API/model use. It reported missing optional PDF/SQL parsers and files without extracted symbols; those are graph coverage limits, not application test failures. Generated `graphify-out/` remains local and untracked, as at the source worktree.
|
||||
|
||||
Durable machine-readable red/final result names, outcomes, counts and timestamps: [verification.json](evidence/rules-freshness/verification.json). Exact native red, development-green and final-regression TRX files are preserved as `.trx.gz` files alongside it. [native-receipts.json](evidence/rules-freshness/native-receipts.json) records raw/compressed SHA256 hashes and byte lengths; gzip decompression reproduces the original receipts without text transformations. The seven-test development-green run overlaps the final regression run.
|
||||
|
||||
Commands use the installed `C:\Users\Connor\.dotnet\dotnet.exe` SDK; the runtime-only Program Files executable cannot execute SDK commands. Test command: `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --no-restore --filter "FullyQualifiedName~RuleSettingsFreshnessTests|FullyQualifiedName~JobQueryParityTests|FullyQualifiedName~JobApplicationsWorkflowSignalsTests|FullyQualifiedName~RulesEngineProspectTests|FullyQualifiedName~ConcurrentInitializationTests"`.
|
||||
|
||||
## Limits and rollback
|
||||
|
||||
The seven-test green development run overlaps the final 35-test run and is not added to its total. The controlled older-request check is not a database isolation stress test. Failed-save injection, hosted MariaDB execution, multi-process load and production latency were not run. This does not qualify Phase 10, integrated security or release readiness. Reverting the package restores the old caching behavior and reintroduces the reproduced stale-settings defect. Publication/integration remains with the parent development lane.
|
||||
@@ -0,0 +1,14 @@
|
||||
# PERF-07 · Page-scoped application correspondence
|
||||
|
||||
Base `327d99dfdacc16f72e008807ea3f27805cf0c570` on `codex/a3-ui-10`. The ordinary applications table fetched the latest correspondence group for every owned application before paging. It now queries the existing latest-message aggregate once for the current page IDs. The normal board and empty page skip that unused aggregate. Follow-up and readiness filters still evaluate their existing full candidate set before paging to preserve membership and totals.
|
||||
|
||||
The focused SQLite test records and replays the actual SQL aggregate. Each fixture contains one correspondence group per owned application, one foreign application with correspondence, and a 15-row second page. The old runtime returned 250 and 2,500 aggregate rows. The new runtime returns exactly the 15 groups belonging to the page in both fixtures. The ordinary board and empty page now issue zero correspondence aggregate commands. The existing tenant filter, ordering, latest-message logic and response shapes are unchanged.
|
||||
|
||||
| Owned applications | Before aggregate rows | After aggregate rows |
|
||||
| ---: | ---: | ---: |
|
||||
| 250 | 250 | 15 |
|
||||
| 2,500 | 2,500 | 15 |
|
||||
|
||||
**PASSED** 36 selected Release tests with pinned SDK 9.0.317 and no restore. 18 JobQueryParity, 10 ApplicationCalendar, five RulesEngineProspect and three OwnershipGuard cases. The 16 existing parity cases cover ordering, filters, board, ownership and pagination. Two expected pre-fix failures are preserved. [Native red and final test logs](../ui-modernisation/evidence/perf-job-page/)
|
||||
|
||||
These counts measure rows returned by the aggregate under a disposable SQLite fixture. MariaDB plan/rows examined, API response time and production performance remain unmeasured. No index, migration or worker configuration changed.
|
||||
@@ -0,0 +1,205 @@
|
||||
{
|
||||
"chromium": "151.0.7922.34",
|
||||
"repetitions": 1,
|
||||
"fixtureJobs": 15,
|
||||
"profiles": [
|
||||
{
|
||||
"name": "desktop",
|
||||
"viewport": {
|
||||
"width": 1366,
|
||||
"height": 900
|
||||
},
|
||||
"latencyMs": 40,
|
||||
"downloadKbps": 10000,
|
||||
"uploadKbps": 5000,
|
||||
"cpu": 1
|
||||
},
|
||||
{
|
||||
"name": "mobile",
|
||||
"viewport": {
|
||||
"width": 390,
|
||||
"height": 844
|
||||
},
|
||||
"isMobile": true,
|
||||
"hasTouch": true,
|
||||
"deviceScaleFactor": 3,
|
||||
"latencyMs": 150,
|
||||
"downloadKbps": 1600,
|
||||
"uploadKbps": 750,
|
||||
"cpu": 4
|
||||
}
|
||||
],
|
||||
"exports": {
|
||||
"baseline": {
|
||||
"root": "C:\\Users\\Connor\\AppData\\Local\\Temp\\a3-jobs-baseline-6bfdbd9d",
|
||||
"indexSha256": "0c85270af2322b269312e76aa8ce14b5748d03ae4fd61ee3a611f2af617db68c"
|
||||
},
|
||||
"candidate": {
|
||||
"root": "C:\\Users\\Connor\\.codex\\worktrees\\direct-roadmap-integration\\Job tracker\\job-tracker-ui\\out",
|
||||
"indexSha256": "6c99c2c1b31cd567025e38add38c7c0300a04339c73f83b6068c5a326b995931"
|
||||
}
|
||||
},
|
||||
"caveats": "Synthetic GET fixtures are immediately fulfilled, third-party calls are blocked, assets are uncompressed on loopback, sampled LCP/layout shifts are lab observations.",
|
||||
"medians": [
|
||||
{
|
||||
"profile": "desktop",
|
||||
"path": "/jobs",
|
||||
"build": "baseline",
|
||||
"contentMs": 2472,
|
||||
"jsRawBytes": 2052915,
|
||||
"jsGzip6Estimate": 606602
|
||||
},
|
||||
{
|
||||
"profile": "desktop",
|
||||
"path": "/jobs",
|
||||
"build": "candidate",
|
||||
"contentMs": 2445,
|
||||
"jsRawBytes": 2052966,
|
||||
"jsGzip6Estimate": 606643
|
||||
},
|
||||
{
|
||||
"profile": "mobile",
|
||||
"path": "/jobs",
|
||||
"build": "baseline",
|
||||
"contentMs": 13455,
|
||||
"jsRawBytes": 2052915,
|
||||
"jsGzip6Estimate": 606602
|
||||
},
|
||||
{
|
||||
"profile": "mobile",
|
||||
"path": "/jobs",
|
||||
"build": "candidate",
|
||||
"contentMs": 13233,
|
||||
"jsRawBytes": 2052966,
|
||||
"jsGzip6Estimate": 606643
|
||||
}
|
||||
],
|
||||
"samples": [
|
||||
{
|
||||
"trial": 1,
|
||||
"profile": "desktop",
|
||||
"build": "baseline",
|
||||
"path": "/jobs",
|
||||
"localeReadDelta": 1,
|
||||
"contentMs": 2472,
|
||||
"sampledLcpMs": 2252,
|
||||
"observedLayoutShiftSum": 0.23809328599150012,
|
||||
"js": {
|
||||
"files": 20,
|
||||
"raw": 2052915,
|
||||
"gzip6Estimate": 606602
|
||||
},
|
||||
"css": {
|
||||
"files": 1,
|
||||
"raw": 293,
|
||||
"gzip6Estimate": 227
|
||||
},
|
||||
"api": [
|
||||
"/api/auth/config",
|
||||
"/api/auth/me",
|
||||
"/api/jobapplications/reminders?upcomingDays=14",
|
||||
"/api/notifications/unread-count",
|
||||
"/api/companies",
|
||||
"/api/jobapplications?page=1&pageSize=15&includeDeleted=false&sortBy=dateApplied&sortDir=desc",
|
||||
"/api/jobapplications?page=1&pageSize=15&includeDeleted=false&sortBy=dateApplied&sortDir=desc"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"trial": 1,
|
||||
"profile": "desktop",
|
||||
"build": "candidate",
|
||||
"path": "/jobs",
|
||||
"localeReadDelta": 0,
|
||||
"contentMs": 2445,
|
||||
"sampledLcpMs": 2208,
|
||||
"observedLayoutShiftSum": 0.23809328599150012,
|
||||
"js": {
|
||||
"files": 20,
|
||||
"raw": 2052966,
|
||||
"gzip6Estimate": 606643
|
||||
},
|
||||
"css": {
|
||||
"files": 1,
|
||||
"raw": 293,
|
||||
"gzip6Estimate": 227
|
||||
},
|
||||
"api": [
|
||||
"/api/auth/config",
|
||||
"/api/auth/me",
|
||||
"/api/jobapplications/reminders?upcomingDays=14",
|
||||
"/api/notifications/unread-count",
|
||||
"/api/companies",
|
||||
"/api/jobapplications?page=1&pageSize=15&includeDeleted=false&sortBy=dateApplied&sortDir=desc"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"trial": 1,
|
||||
"profile": "mobile",
|
||||
"build": "baseline",
|
||||
"path": "/jobs",
|
||||
"localeReadDelta": 1,
|
||||
"contentMs": 13455,
|
||||
"sampledLcpMs": 12668,
|
||||
"observedLayoutShiftSum": 0.03510786324402371,
|
||||
"js": {
|
||||
"files": 20,
|
||||
"raw": 2052915,
|
||||
"gzip6Estimate": 606602
|
||||
},
|
||||
"css": {
|
||||
"files": 1,
|
||||
"raw": 293,
|
||||
"gzip6Estimate": 227
|
||||
},
|
||||
"api": [
|
||||
"/api/auth/config",
|
||||
"/api/auth/me",
|
||||
"/api/jobapplications/reminders?upcomingDays=14",
|
||||
"/api/notifications/unread-count",
|
||||
"/api/companies",
|
||||
"/api/jobapplications?page=1&pageSize=15&includeDeleted=false&sortBy=dateApplied&sortDir=desc",
|
||||
"/api/jobapplications?page=1&pageSize=15&includeDeleted=false&sortBy=dateApplied&sortDir=desc"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"trial": 1,
|
||||
"profile": "mobile",
|
||||
"build": "candidate",
|
||||
"path": "/jobs",
|
||||
"localeReadDelta": 0,
|
||||
"contentMs": 13233,
|
||||
"sampledLcpMs": 12492,
|
||||
"observedLayoutShiftSum": 0.03510786324402371,
|
||||
"js": {
|
||||
"files": 20,
|
||||
"raw": 2052966,
|
||||
"gzip6Estimate": 606643
|
||||
},
|
||||
"css": {
|
||||
"files": 1,
|
||||
"raw": 293,
|
||||
"gzip6Estimate": 227
|
||||
},
|
||||
"api": [
|
||||
"/api/auth/config",
|
||||
"/api/auth/me",
|
||||
"/api/jobapplications/reminders?upcomingDays=14",
|
||||
"/api/notifications/unread-count",
|
||||
"/api/companies",
|
||||
"/api/jobapplications?page=1&pageSize=15&includeDeleted=false&sortBy=dateApplied&sortDir=desc"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"format": "Native VSTest TRX compressed with gzip; no text transformations",
|
||||
"receipts": [
|
||||
{
|
||||
"rawFile": "rules-red.trx",
|
||||
"rawBytes": 30627,
|
||||
"rawSha256": "c74e5e9703924e1a1775bddab662d8327f3d66ce502ca61d917cd827317e9d68",
|
||||
"compressedFile": "rules-red.trx.gz",
|
||||
"compressedBytes": 2844,
|
||||
"compressedSha256": "630785b741059e1398e777f0c8f84bdf3f7e748844547d7c468ec913cf0261aa"
|
||||
},
|
||||
{
|
||||
"rawFile": "rules-green.trx",
|
||||
"rawBytes": 12087,
|
||||
"rawSha256": "7960a65a79f9208178d91b41a47469c7839ef4e8c352d077d7fe0fa7745354b3",
|
||||
"compressedFile": "rules-green.trx.gz",
|
||||
"compressedBytes": 2092,
|
||||
"compressedSha256": "131c814b17df0fbbde67dea15ed9e65db2e1f2c801afada903453b504b4a64f6"
|
||||
},
|
||||
{
|
||||
"rawFile": "rules-regression.trx",
|
||||
"rawBytes": 53741,
|
||||
"rawSha256": "e2e7e51902a167cdcb6fa46339476759f63331863f5a2953e3d64cf08b97b106",
|
||||
"compressedFile": "rules-regression.trx.gz",
|
||||
"compressedBytes": 6020,
|
||||
"compressedSha256": "7c229b8beb9d2fa8f3ff453f58d5f3cfeac8987d1f79c0bac65db1a55c0883ca"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"baseline": "9c9fe48d5f321c653049f09ced5b7e27701fe2a8",
|
||||
"scope": "Offline SQLite and mocked identity; no models/providers",
|
||||
"red": {
|
||||
"times": {
|
||||
"creation": "2026-11-10T23:15:22.2984079+01:00",
|
||||
"queuing": "2026-11-10T23:15:22.2984084+01:00",
|
||||
"start": "2026-11-10T23:15:19.6116487+01:00",
|
||||
"finish": "2026-11-10T23:15:22.3054244+01:00"
|
||||
},
|
||||
"counters": {
|
||||
"total": "7",
|
||||
"executed": "7",
|
||||
"passed": "0",
|
||||
"failed": "7",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"detail\")",
|
||||
"outcome": "Failed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"reminders\")",
|
||||
"outcome": "Failed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saving_owner_a_does_not_change_owner_b_and_old_readers_do_not_republish_stale_settings",
|
||||
"outcome": "Failed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Global_save_refreshes_fallback_but_preserves_explicit_owner_override",
|
||||
"outcome": "Failed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"readiness\")",
|
||||
"outcome": "Failed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"board\")",
|
||||
"outcome": "Failed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"list\")",
|
||||
"outcome": "Failed"
|
||||
}
|
||||
]
|
||||
},
|
||||
"regression": {
|
||||
"times": {
|
||||
"creation": "2026-11-10T23:16:27.2319904+01:00",
|
||||
"queuing": "2026-11-10T23:16:27.2319908+01:00",
|
||||
"start": "2026-11-10T23:16:25.2545706+01:00",
|
||||
"finish": "2026-11-10T23:16:31.6005940+01:00"
|
||||
},
|
||||
"counters": {
|
||||
"total": "35",
|
||||
"executed": "35",
|
||||
"passed": "35",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"needs-work\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"readiness\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"correspondence\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 2500)",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"custom\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: \"Saved\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RulesEngineProspectTests.An_applied_job_with_no_applied_date_is_not_ghosted",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"combined\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"follow-up\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobApplicationsWorkflowSignalsTests.Readiness_keeps_package_gap_when_notes_do_not_contain_saved_answer_block",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"standard\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"foreign-company\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saving_owner_a_preserves_owner_b_and_existing_readers_see_subsequent_writes",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"deleted\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"interview\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.ConcurrentInitializationTests.Concurrent_checklist_reads_share_the_single_default_item_set",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: \"Interested\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"notes\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"detail\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.ConcurrentInitializationTests.Concurrent_rule_reads_share_the_single_created_settings_row",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 250)",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"list\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"none\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"location\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: \"Preparing\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RulesEngineProspectTests.An_applied_job_past_the_threshold_still_ghosts",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"reminders\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"include-deleted\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"company\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Saved_owner_thresholds_are_visible_on_the_next_read(surface: \"board\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"all\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Completing_an_older_request_cannot_restore_old_rules_after_a_save",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.RuleSettingsFreshnessTests.Global_save_refreshes_fallback_but_preserves_explicit_owner_override",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: \"search\")",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"test": "JobTrackerApi.Tests.JobApplicationsWorkflowSignalsTests.Reminders_return_normalized_workflow_routes_for_package_and_follow_up_actions",
|
||||
"outcome": "Passed"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ Owner addendum received 9 November 2026. Source `E:/Storage/Projects/Active/temp
|
||||
| --- | --- | --- |
|
||||
| Admin information isolation | The original redaction patch passed 62 tests on the security branch. [A3 integration](ADMIN_AUDIT_ISOLATION_VALIDATION.md) matched the exact source/test patch and passed 57 selected tests. The runs overlap and remain separate evidence. | Integrated security, remaining delivery paths, broader minimisation and deployment checks remain separate. |
|
||||
| Discover Jobs | [Search-first layout](visual-correction/DISCOVERY_SEARCH_FIRST.md) moves the query above filters and qualifies the existing NAV request, keyboard submit and source disclosure. | Expose new filters, map and multilingual suggestions only with qualified data and the existing GJ architecture. Mobile filter drawer and focused detail remain open. |
|
||||
| Applications | [Title-first rows and explicit bulk mode](visual-correction/APPLICATION_SELECTION_REVIEW.md) qualified at 36 configurations. | Secondary action consolidation and final native/visual review remain open. |
|
||||
| Admin Users and Audit | [Aligned rows](visual-correction/ADMIN_USER_ALIGNMENT_REVIEW.md), [read-only 2FA status](visual-correction/ADMIN_USER_2FA_REVIEW.md) and [recent audit filtering and details](visual-correction/AUDIT_FILTERS_REVIEW.md) passed their own 36-configuration checks. Compact user actions and additional structured filters remain open. | 2FA recovery and private support access require explicit owner approval of their technical and privacy designs. |
|
||||
| Applications | [Title-first rows and explicit bulk mode](visual-correction/APPLICATION_SELECTION_REVIEW.md) and [compact row actions](visual-correction/APPLICATION_ACTIONS_REVIEW.md) qualified at 36 configurations each. | Final native/visual review and broader server-backed workflows remain open. |
|
||||
| Admin Users and Audit | [Compact user actions](visual-correction/ADMIN_USER_ACTIONS_REVIEW.md) preserve alignment and read-only 2FA. [Recent audit filtering and details](visual-correction/AUDIT_FILTERS_REVIEW.md) passed its own 36-configuration checks. Additional audit filters remain open. | 2FA recovery and private support access require explicit owner approval of their technical and privacy designs. |
|
||||
| Job Correspondence | Continue inbox layout, mailbox-status presentation and existing explicit consent flow. | Provider verification, restricted scopes, multiple-account persistence and retention decisions retain their gates. Signing in grants no mailbox access. |
|
||||
| System Status | [Status refresh evidence](visual-correction/SYSTEM_STATUS_REFRESH_REVIEW.md) and [diagnostics design](SYSTEM_DIAGNOSTICS_DESIGN.md) distinguish current, stale and unavailable readings. CV Benchmark Review is retained. | Predefined diagnostics require approved suites, isolated execution, role checks and audit. Live execution and per-signal telemetry remain open. |
|
||||
| Terminology | “Prepare application” / “Klargjør søknaden” is visible in the scoped EN/NB application checks. | Continue broader terminology and European catalogue review. |
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# A3-IM10 Cross-application qualification
|
||||
|
||||
Applications runtime `bfbfaeb9` consolidates existing row controls into one keyboard menu while preserving selection, status, edit, Trash and Restore. See [application action review](visual-correction/APPLICATION_ACTIONS_REVIEW.md).
|
||||
|
||||
Admin Users runtime `171a6908` groups existing row actions into one keyboard menu. See [Admin action evidence](visual-correction/ADMIN_USER_ACTIONS_REVIEW.md).
|
||||
|
||||
Audit runtime `cd69b769` combines exact event type and inclusive local dates with recent search and adds keyboard-expandable details for already permitted values. See [Audit filter review](visual-correction/AUDIT_FILTERS_REVIEW.md).
|
||||
|
||||
Audit runtime `1a8a97a5` adds local metadata search for the loaded recent-event window. Ten frontend tests and 72 controlled captures and scans passed. See [audit search evidence](visual-correction/AUDIT_SEARCH_REVIEW.md).
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
PASSED ESLint with zero warnings for useCompanies.ts and account-scoped-state.test.tsx
|
||||
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TestRun id="cef5c298-8e5f-4dce-9773-9425e2b243f2" name="Connor@CESNIMDA 2026-11-10 17:40:20" runUser="Cesnimda\Connor" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||
<Times creation="2026-11-10T17:40:20.2812089+01:00" queuing="2026-11-10T17:40:20.2812094+01:00" start="2026-11-10T17:40:12.6071553+01:00" finish="2026-11-10T17:40:20.7722299+01:00" />
|
||||
<TestSettings name="default" id="a1199284-99a7-429d-b082-6cc8e2b300be">
|
||||
<Deployment runDeploymentRoot="Connor_CESNIMDA_2026-11-10_17_40_20" />
|
||||
</TestSettings>
|
||||
<Results>
|
||||
<UnitTestResult executionId="543ffa88-d4a2-4125-8c35-1db3e010c386" testId="1ffc3039-bc58-2cb9-9ee2-3abae47b2e11" testName="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 2500)" computerName="CESNIMDA" duration="00:00:06.1888194" startTime="2026-11-10T17:40:20.2276096+01:00" endTime="2026-11-10T17:40:20.2276734+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Failed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="543ffa88-d4a2-4125-8c35-1db3e010c386">
|
||||
<Output>
|
||||
<ErrorInfo>
|
||||
<Message>Assert.Equal() Failure: Values differ
|
||||
Expected: 15
|
||||
Actual: 2500</Message>
|
||||
<StackTrace> at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 72
|
||||
at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 78
|
||||
at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 78
|
||||
at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 78
|
||||
--- End of stack trace from previous location ---</StackTrace>
|
||||
</ErrorInfo>
|
||||
</Output>
|
||||
</UnitTestResult>
|
||||
<UnitTestResult executionId="bda9fa1c-a1df-458a-8efd-930eac003725" testId="b4d52926-057b-e1a5-2803-210ea3dabd5d" testName="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 250)" computerName="CESNIMDA" duration="00:00:00.4458448" startTime="2026-11-10T17:40:20.6592826+01:00" endTime="2026-11-10T17:40:20.6592828+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Failed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="bda9fa1c-a1df-458a-8efd-930eac003725">
|
||||
<Output>
|
||||
<ErrorInfo>
|
||||
<Message>Assert.Equal() Failure: Values differ
|
||||
Expected: 15
|
||||
Actual: 250</Message>
|
||||
<StackTrace> at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 72
|
||||
at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 78
|
||||
at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 78
|
||||
at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size) in C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs:line 78
|
||||
--- End of stack trace from previous location ---</StackTrace>
|
||||
</ErrorInfo>
|
||||
</Output>
|
||||
</UnitTestResult>
|
||||
</Results>
|
||||
<TestDefinitions>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 2500)" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="1ffc3039-bc58-2cb9-9ee2-3abae47b2e11">
|
||||
<Execution id="543ffa88-d4a2-4125-8c35-1db3e010c386" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 250)" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="b4d52926-057b-e1a5-2803-210ea3dabd5d">
|
||||
<Execution id="bda9fa1c-a1df-458a-8efd-930eac003725" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page" />
|
||||
</UnitTest>
|
||||
</TestDefinitions>
|
||||
<TestEntries>
|
||||
<TestEntry testId="1ffc3039-bc58-2cb9-9ee2-3abae47b2e11" executionId="543ffa88-d4a2-4125-8c35-1db3e010c386" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="b4d52926-057b-e1a5-2803-210ea3dabd5d" executionId="bda9fa1c-a1df-458a-8efd-930eac003725" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
</TestEntries>
|
||||
<TestLists>
|
||||
<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
|
||||
</TestLists>
|
||||
<ResultSummary outcome="Failed">
|
||||
<Counters total="2" executed="2" passed="0" failed="2" error="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />
|
||||
<Output>
|
||||
<StdOut>[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 9.0.19)
|
||||
[xUnit.net 00:00:00.50] Discovering: JobTrackerApi.Tests
|
||||
[xUnit.net 00:00:00.65] Discovered: JobTrackerApi.Tests
|
||||
[xUnit.net 00:00:00.66] Starting: JobTrackerApi.Tests
|
||||
[xUnit.net 00:00:06.90] Assert.Equal() Failure: Values differ
|
||||
[xUnit.net 00:00:06.90] Expected: 15
|
||||
[xUnit.net 00:00:06.90] Actual: 2500
|
||||
[xUnit.net 00:00:06.90] Stack Trace:
|
||||
[xUnit.net 00:00:06.91] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(72,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:06.91] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(78,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:06.91] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(78,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:06.91] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(78,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:06.91] --- End of stack trace from previous location ---
|
||||
[xUnit.net 00:00:07.34] Assert.Equal() Failure: Values differ
|
||||
[xUnit.net 00:00:07.34] Expected: 15
|
||||
[xUnit.net 00:00:07.34] Actual: 250
|
||||
[xUnit.net 00:00:07.34] Stack Trace:
|
||||
[xUnit.net 00:00:07.34] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(72,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:07.34] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(78,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:07.34] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(78,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:07.34] C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\JobQueryParityTests.cs(78,0): at JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(Int32 size)
|
||||
[xUnit.net 00:00:07.34] --- End of stack trace from previous location ---
|
||||
[xUnit.net 00:00:07.35] Finished: JobTrackerApi.Tests
|
||||
</StdOut>
|
||||
</Output>
|
||||
<RunInfos>
|
||||
<RunInfo computerName="CESNIMDA" outcome="Error" timestamp="2026-11-10T17:40:20.2162764+01:00">
|
||||
<Text>[xUnit.net 00:00:06.90] JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 2500) [FAIL]</Text>
|
||||
</RunInfo>
|
||||
<RunInfo computerName="CESNIMDA" outcome="Error" timestamp="2026-11-10T17:40:20.6587289+01:00">
|
||||
<Text>[xUnit.net 00:00:07.34] JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 250) [FAIL]</Text>
|
||||
</RunInfo>
|
||||
</RunInfos>
|
||||
</ResultSummary>
|
||||
</TestRun>
|
||||
@@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TestRun id="0eb688ae-932f-400e-b549-5d643663f254" name="Connor@CESNIMDA 2026-11-10 17:40:58" runUser="Cesnimda\Connor" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||
<Times creation="2026-11-10T17:40:58.9969509+01:00" queuing="2026-11-10T17:40:58.9969514+01:00" start="2026-11-10T17:40:57.8896843+01:00" finish="2026-11-10T17:41:09.0688211+01:00" />
|
||||
<TestSettings name="default" id="64984d30-be08-46dc-9f60-60a55e88bfec">
|
||||
<Deployment runDeploymentRoot="Connor_CESNIMDA_2026-11-10_17_40_58" />
|
||||
</TestSettings>
|
||||
<Results>
|
||||
<UnitTestResult executionId="d514a9d8-d74b-4bd5-9d64-b148bd240605" testId="b2951d7e-9ec2-af59-3389-f50ca75dc688" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_rejects_unbounded_or_invalid_ranges(from: "2026-01-01", to: "2026-12-31")" computerName="CESNIMDA" duration="00:00:00.0008152" startTime="2026-11-10T17:41:00.3823072+01:00" endTime="2026-11-10T17:41:00.3823074+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="d514a9d8-d74b-4bd5-9d64-b148bd240605" />
|
||||
<UnitTestResult executionId="2da5ddb6-ec56-4225-8854-113af8e1ea0e" testId="ee88b8e2-383e-d7d0-52bc-8593a0cd45b2" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_rejects_unbounded_or_invalid_ranges(from: "9999-12-01", to: "9999-12-31")" computerName="CESNIMDA" duration="00:00:00.0002468" startTime="2026-11-10T17:41:00.3831390+01:00" endTime="2026-11-10T17:41:00.3831395+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="2da5ddb6-ec56-4225-8854-113af8e1ea0e" />
|
||||
<UnitTestResult executionId="04dcdb73-32bb-4917-9763-306549743af3" testId="243583b0-ea8a-0c2d-b704-f9c081502a8c" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "interview")" computerName="CESNIMDA" duration="00:00:00.3130682" startTime="2026-11-10T17:41:01.4958918+01:00" endTime="2026-11-10T17:41:01.4958922+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="04dcdb73-32bb-4917-9763-306549743af3" />
|
||||
<UnitTestResult executionId="7ab77d8d-de8b-448f-b105-2cc93fc4c67f" testId="63a1c947-a202-ef7f-514d-09b47ec75ee2" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "search")" computerName="CESNIMDA" duration="00:00:00.2832366" startTime="2026-11-10T17:41:03.9228872+01:00" endTime="2026-11-10T17:41:03.9228874+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="7ab77d8d-de8b-448f-b105-2cc93fc4c67f" />
|
||||
<UnitTestResult executionId="e4c86caf-db24-4ceb-9a2f-f30583fc8ef0" testId="04660ada-cf1a-cf8c-ac49-1aa92a2f1595" testName="JobTrackerApi.Tests.OwnershipGuardTests.Correspondence_controller_has_owned_message_lookup_helper" computerName="CESNIMDA" duration="00:00:00.0045881" startTime="2026-11-10T17:40:58.9065839+01:00" endTime="2026-11-10T17:40:58.9066182+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="e4c86caf-db24-4ceb-9a2f-f30583fc8ef0" />
|
||||
<UnitTestResult executionId="6cc6c76a-f3a9-4fb9-bebb-2123a43b3194" testId="57096417-b25e-42cc-c6aa-1bf95fed407a" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "follow-up")" computerName="CESNIMDA" duration="00:00:00.1735792" startTime="2026-11-10T17:41:01.6695298+01:00" endTime="2026-11-10T17:41:01.6695309+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="6cc6c76a-f3a9-4fb9-bebb-2123a43b3194" />
|
||||
<UnitTestResult executionId="e60af608-3ae0-48a7-968c-1a486811ef70" testId="8ee9db5a-f803-b7e2-3c34-baac5edb34c8" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_includes_saved_deadlines_and_preserves_recorded_dates_without_provider_access" computerName="CESNIMDA" duration="00:00:00.0042812" startTime="2026-11-10T17:41:00.4150922+01:00" endTime="2026-11-10T17:41:00.4150924+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="e60af608-3ae0-48a7-968c-1a486811ef70" />
|
||||
<UnitTestResult executionId="981ee887-8fcf-469a-88b1-d94cf7b49665" testId="c14f173e-4368-76ea-1308-148f5a610ee7" testName="JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: "Saved")" computerName="CESNIMDA" duration="00:00:00.0003160" startTime="2026-11-10T17:40:58.9114719+01:00" endTime="2026-11-10T17:40:58.9114720+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="981ee887-8fcf-469a-88b1-d94cf7b49665" />
|
||||
<UnitTestResult executionId="04ae9640-c657-4295-bafb-f6bf97e568db" testId="1ffc3039-bc58-2cb9-9ee2-3abae47b2e11" testName="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 2500)" computerName="CESNIMDA" duration="00:00:04.4181430" startTime="2026-11-10T17:41:08.7006586+01:00" endTime="2026-11-10T17:41:08.7006589+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="04ae9640-c657-4295-bafb-f6bf97e568db" />
|
||||
<UnitTestResult executionId="2251d469-53c6-429b-af33-9d56fa6895ec" testId="57a70a0d-843e-eb80-0342-f2e1d017491c" testName="JobTrackerApi.Tests.RulesEngineProspectTests.An_applied_job_with_no_applied_date_is_not_ghosted" computerName="CESNIMDA" duration="00:00:00.0066359" startTime="2026-11-10T17:40:58.9094725+01:00" endTime="2026-11-10T17:40:58.9094727+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="2251d469-53c6-429b-af33-9d56fa6895ec" />
|
||||
<UnitTestResult executionId="6122aa5c-f7a7-4e4a-b413-525ee34367d1" testId="eb7a20fa-63ab-b655-d3f0-046e269b171c" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_rejects_unbounded_or_invalid_ranges(from: "2026-09-30", to: "2026-09-01")" computerName="CESNIMDA" duration="00:00:00.0004290" startTime="2026-11-10T17:41:00.3828543+01:00" endTime="2026-11-10T17:41:00.3828546+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="6122aa5c-f7a7-4e4a-b413-525ee34367d1" />
|
||||
<UnitTestResult executionId="303f9c3e-e004-4e14-8007-1ce5761a31dd" testId="a5089dc5-fff8-aece-6968-d45c244cfd94" testName="JobTrackerApi.Tests.OwnershipGuardTests.Summarizer_service_uses_sha256_cache_key_builder" computerName="CESNIMDA" duration="00:00:00.0067803" startTime="2026-11-10T17:40:58.9129520+01:00" endTime="2026-11-10T17:40:58.9129526+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="303f9c3e-e004-4e14-8007-1ce5761a31dd" />
|
||||
<UnitTestResult executionId="f5fe9e01-29d8-4ded-8238-f7eb4ca481d2" testId="9634ef4e-56ca-8e7e-717e-86049cac7b6b" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Downloads_portable_all_day_deadline_event_without_provider_credentials" computerName="CESNIMDA" duration="00:00:00.0861264" startTime="2026-11-10T17:41:00.1864108+01:00" endTime="2026-11-10T17:41:00.1864110+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="f5fe9e01-29d8-4ded-8238-f7eb4ca481d2" />
|
||||
<UnitTestResult executionId="b84b6463-2659-452e-af58-25dae568993e" testId="e4227296-3fbb-0af0-0d38-a3229e8a3931" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "custom")" computerName="CESNIMDA" duration="00:00:00.2636922" startTime="2026-11-10T17:41:02.1993685+01:00" endTime="2026-11-10T17:41:02.1993694+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="b84b6463-2659-452e-af58-25dae568993e" />
|
||||
<UnitTestResult executionId="254591dc-0218-4dd0-942c-b80219b885d9" testId="1ece7e57-e724-aa88-aaa8-6eccd169f3a6" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "include-deleted")" computerName="CESNIMDA" duration="00:00:00.2391848" startTime="2026-11-10T17:41:00.7496184+01:00" endTime="2026-11-10T17:41:00.7496187+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="254591dc-0218-4dd0-942c-b80219b885d9" />
|
||||
<UnitTestResult executionId="169c222e-dfc2-4ea2-b7d8-244182df48df" testId="b3acf8bc-3ec2-abff-6541-a96daa604534" testName="JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: "Preparing")" computerName="CESNIMDA" duration="00:00:00.0001544" startTime="2026-11-10T17:40:58.9114312+01:00" endTime="2026-11-10T17:40:58.9114312+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="169c222e-dfc2-4ea2-b7d8-244182df48df" />
|
||||
<UnitTestResult executionId="8e738f34-9348-40d0-9f05-fc68dfd68f07" testId="6f507120-70ec-fc23-9a9c-b5662af9e900" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Creates_follow_up_in_selected_connected_calendar_with_stable_job_context" computerName="CESNIMDA" duration="00:00:00.0054204" startTime="2026-11-10T17:41:00.4106869+01:00" endTime="2026-11-10T17:41:00.4106870+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="8e738f34-9348-40d0-9f05-fc68dfd68f07" />
|
||||
<UnitTestResult executionId="ab124cfe-ea29-4767-bbc0-cf1a26998d80" testId="e5a658bc-a9ee-f8a6-00da-31a875195d4a" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_date_window_translates_on_sqlite_and_keeps_legacy_wall_clock_date" computerName="CESNIMDA" duration="00:00:00.1948940" startTime="2026-11-10T17:41:00.3814362+01:00" endTime="2026-11-10T17:41:00.3814363+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="ab124cfe-ea29-4767-bbc0-cf1a26998d80" />
|
||||
<UnitTestResult executionId="126f9edf-b4a5-4f5b-af4d-26649a2478b0" testId="b4d52926-057b-e1a5-2803-210ea3dabd5d" testName="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 250)" computerName="CESNIMDA" duration="00:00:00.2820729" startTime="2026-11-10T17:41:08.9827866+01:00" endTime="2026-11-10T17:41:08.9827870+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="126f9edf-b4a5-4f5b-af4d-26649a2478b0" />
|
||||
<UnitTestResult executionId="28aff3d4-f71f-455b-ab84-285c7ef72cd0" testId="c247d002-0f3a-f835-2525-f73d9d342dc3" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Status_distinguishes_connection_from_calendar_consent" computerName="CESNIMDA" duration="00:00:00.0095508" startTime="2026-11-10T17:41:00.4053779+01:00" endTime="2026-11-10T17:41:00.4053785+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="28aff3d4-f71f-455b-ab84-285c7ef72cd0" />
|
||||
<UnitTestResult executionId="f7da2a85-8da9-4421-b4dc-9d2bdfaf38db" testId="2d738780-0c7e-809d-7a36-e22b11e017c3" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Rejects_another_owners_job_without_calling_provider" computerName="CESNIMDA" duration="00:00:00.0124306" startTime="2026-11-10T17:41:00.3956744+01:00" endTime="2026-11-10T17:41:00.3956748+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="f7da2a85-8da9-4421-b4dc-9d2bdfaf38db" />
|
||||
<UnitTestResult executionId="538a2d14-8e33-4057-9354-b3178af82243" testId="ee747285-6574-0968-3d1b-5b4086b49e77" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "location")" computerName="CESNIMDA" duration="00:00:00.2848120" startTime="2026-11-10T17:41:01.1826927+01:00" endTime="2026-11-10T17:41:01.1826932+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="538a2d14-8e33-4057-9354-b3178af82243" />
|
||||
<UnitTestResult executionId="de4ad138-c214-4682-a5a3-ec2619064fff" testId="a75c8efc-b4a8-b8b5-b751-6fee6831ebf4" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "deleted")" computerName="CESNIMDA" duration="00:00:00.2179347" startTime="2026-11-10T17:41:03.1979644+01:00" endTime="2026-11-10T17:41:03.1979649+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="de4ad138-c214-4682-a5a3-ec2619064fff" />
|
||||
<UnitTestResult executionId="e16380b9-dbcc-488b-b5b8-5915895be61d" testId="ce6f8b56-40b6-78ff-93e6-483db0ceaed8" testName="JobTrackerApi.Tests.OwnershipGuardTests.Attachments_controller_has_owned_attachment_lookup_helper" computerName="CESNIMDA" duration="00:00:00.0001421" startTime="2026-11-10T17:40:58.9606250+01:00" endTime="2026-11-10T17:40:58.9606252+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="e16380b9-dbcc-488b-b5b8-5915895be61d" />
|
||||
<UnitTestResult executionId="e4254dcf-ebe3-4f45-88c3-2a391188fa69" testId="84f76a74-2082-ce72-9363-22dca54580d2" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "combined")" computerName="CESNIMDA" duration="00:00:00.3591550" startTime="2026-11-10T17:41:04.2821252+01:00" endTime="2026-11-10T17:41:04.2821254+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="e4254dcf-ebe3-4f45-88c3-2a391188fa69" />
|
||||
<UnitTestResult executionId="7544e0ab-5ccc-4bc4-b696-d30d52a00ac7" testId="9ca882ec-2b75-a26b-1420-961f41c85538" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "correspondence")" computerName="CESNIMDA" duration="00:00:00.2255136" startTime="2026-11-10T17:41:03.4237458+01:00" endTime="2026-11-10T17:41:03.4237463+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="7544e0ab-5ccc-4bc4-b696-d30d52a00ac7" />
|
||||
<UnitTestResult executionId="ce1bb01d-b213-4134-b5d5-3732917d69a7" testId="3cd2fef8-dfa7-1464-b6a9-026485c0bd9e" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "notes")" computerName="CESNIMDA" duration="00:00:00.2739544" startTime="2026-11-10T17:41:02.4734698+01:00" endTime="2026-11-10T17:41:02.4734700+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="ce1bb01d-b213-4134-b5d5-3732917d69a7" />
|
||||
<UnitTestResult executionId="17157738-6866-4749-9a3f-d515b3e4cc8e" testId="1d2f56b0-6892-bc4c-992f-c512e097577a" testName="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_excludes_other_owners_deleted_and_out_of_range_dates" computerName="CESNIMDA" duration="00:00:01.2014749" startTime="2026-11-10T17:41:00.1002034+01:00" endTime="2026-11-10T17:41:00.1002037+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="17157738-6866-4749-9a3f-d515b3e4cc8e" />
|
||||
<UnitTestResult executionId="4425f5c7-8621-4bfb-af23-f70c346fcb3b" testId="161dc999-3648-3d48-1d7b-99ab066de8f6" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "needs-work")" computerName="CESNIMDA" duration="00:00:00.2562041" startTime="2026-11-10T17:41:02.9799339+01:00" endTime="2026-11-10T17:41:02.9799343+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="4425f5c7-8621-4bfb-af23-f70c346fcb3b" />
|
||||
<UnitTestResult executionId="de64afe0-b777-4aa4-85b3-352ab2124a14" testId="5b8ea46d-ee44-6470-1381-3f43ab773db6" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "standard")" computerName="CESNIMDA" duration="00:00:01.6116204" startTime="2026-11-10T17:41:00.5103407+01:00" endTime="2026-11-10T17:41:00.5103409+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="de64afe0-b777-4aa4-85b3-352ab2124a14" />
|
||||
<UnitTestResult executionId="0c9e1d5a-c06e-4748-8963-1f712829809f" testId="a8aff3ef-f27a-a882-1aa1-ba9c663cf4ce" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "company")" computerName="CESNIMDA" duration="00:00:00.2499844" startTime="2026-11-10T17:41:02.7235410+01:00" endTime="2026-11-10T17:41:02.7235411+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="0c9e1d5a-c06e-4748-8963-1f712829809f" />
|
||||
<UnitTestResult executionId="eac6efdf-fe15-4f38-bccd-3ed966be3c4c" testId="4d9cb541-8911-0d74-cb02-8d7f6700dd1f" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "foreign-company")" computerName="CESNIMDA" duration="00:00:00.2657918" startTime="2026-11-10T17:41:01.9354585+01:00" endTime="2026-11-10T17:41:01.9354588+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="eac6efdf-fe15-4f38-bccd-3ed966be3c4c" />
|
||||
<UnitTestResult executionId="0be92dbc-c1f5-48b0-a634-41f2d477c653" testId="ebd693de-f8c6-6887-7e1c-635cc17733a8" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "all")" computerName="CESNIMDA" duration="00:00:00.1479685" startTime="2026-11-10T17:41:00.8978175+01:00" endTime="2026-11-10T17:41:00.8978176+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="0be92dbc-c1f5-48b0-a634-41f2d477c653" />
|
||||
<UnitTestResult executionId="bcaaca56-6cc7-4649-bf36-48265f9b6957" testId="40e20eb7-1334-91dc-68aa-74c908945631" testName="JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: "Interested")" computerName="CESNIMDA" duration="00:00:00.0000215" startTime="2026-11-10T17:40:58.9114975+01:00" endTime="2026-11-10T17:40:58.9114975+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="bcaaca56-6cc7-4649-bf36-48265f9b6957" />
|
||||
<UnitTestResult executionId="14f020b3-579b-4ee6-b859-7130a89e982a" testId="92816c05-8654-d3ce-80e3-2a9beb851f21" testName="JobTrackerApi.Tests.RulesEngineProspectTests.An_applied_job_past_the_threshold_still_ghosts" computerName="CESNIMDA" duration="00:00:00.0004165" startTime="2026-11-10T17:40:58.9115468+01:00" endTime="2026-11-10T17:40:58.9115468+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="14f020b3-579b-4ee6-b859-7130a89e982a" />
|
||||
<UnitTestResult executionId="205773aa-d298-451f-b7eb-98d512131040" testId="83cff8f8-d781-99e7-95b3-2a039270fd7a" testName="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "none")" computerName="CESNIMDA" duration="00:00:00.2156496" startTime="2026-11-10T17:41:03.6395556+01:00" endTime="2026-11-10T17:41:03.6395559+01:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Passed" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" relativeResultsDirectory="205773aa-d298-451f-b7eb-98d512131040" />
|
||||
</Results>
|
||||
<TestDefinitions>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_rejects_unbounded_or_invalid_ranges(from: "9999-12-01", to: "9999-12-31")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="ee88b8e2-383e-d7d0-52bc-8593a0cd45b2">
|
||||
<Execution id="2da5ddb6-ec56-4225-8854-113af8e1ea0e" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Agenda_rejects_unbounded_or_invalid_ranges" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_rejects_unbounded_or_invalid_ranges(from: "2026-09-30", to: "2026-09-01")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="eb7a20fa-63ab-b655-d3f0-046e269b171c">
|
||||
<Execution id="6122aa5c-f7a7-4e4a-b413-525ee34367d1" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Agenda_rejects_unbounded_or_invalid_ranges" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "notes")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="3cd2fef8-dfa7-1464-b6a9-026485c0bd9e">
|
||||
<Execution id="ce1bb01d-b213-4134-b5d5-3732917d69a7" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_includes_saved_deadlines_and_preserves_recorded_dates_without_provider_access" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="8ee9db5a-f803-b7e2-3c34-baac5edb34c8">
|
||||
<Execution id="e60af608-3ae0-48a7-968c-1a486811ef70" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Agenda_includes_saved_deadlines_and_preserves_recorded_dates_without_provider_access" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "foreign-company")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="4d9cb541-8911-0d74-cb02-8d7f6700dd1f">
|
||||
<Execution id="eac6efdf-fe15-4f38-bccd-3ed966be3c4c" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_excludes_other_owners_deleted_and_out_of_range_dates" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="1d2f56b0-6892-bc4c-992f-c512e097577a">
|
||||
<Execution id="17157738-6866-4749-9a3f-d515b3e4cc8e" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Agenda_excludes_other_owners_deleted_and_out_of_range_dates" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: "Interested")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="40e20eb7-1334-91dc-68aa-74c908945631">
|
||||
<Execution id="bcaaca56-6cc7-4649-bf36-48265f9b6957" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.RulesEngineProspectTests" name="A_prospect_is_never_followed_up_or_ghosted_however_old" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: "Saved")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="c14f173e-4368-76ea-1308-148f5a610ee7">
|
||||
<Execution id="981ee887-8fcf-469a-88b1-d94cf7b49665" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.RulesEngineProspectTests" name="A_prospect_is_never_followed_up_or_ghosted_however_old" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.OwnershipGuardTests.Correspondence_controller_has_owned_message_lookup_helper" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="04660ada-cf1a-cf8c-ac49-1aa92a2f1595">
|
||||
<Execution id="e4c86caf-db24-4ceb-9a2f-f30583fc8ef0" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.OwnershipGuardTests" name="Correspondence_controller_has_owned_message_lookup_helper" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.OwnershipGuardTests.Attachments_controller_has_owned_attachment_lookup_helper" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="ce6f8b56-40b6-78ff-93e6-483db0ceaed8">
|
||||
<Execution id="e16380b9-dbcc-488b-b5b8-5915895be61d" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.OwnershipGuardTests" name="Attachments_controller_has_owned_attachment_lookup_helper" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "follow-up")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="57096417-b25e-42cc-c6aa-1bf95fed407a">
|
||||
<Execution id="6cc6c76a-f3a9-4fb9-bebb-2123a43b3194" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "deleted")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="a75c8efc-b4a8-b8b5-b751-6fee6831ebf4">
|
||||
<Execution id="de4ad138-c214-4682-a5a3-ec2619064fff" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Status_distinguishes_connection_from_calendar_consent" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="c247d002-0f3a-f835-2525-f73d9d342dc3">
|
||||
<Execution id="28aff3d4-f71f-455b-ab84-285c7ef72cd0" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Status_distinguishes_connection_from_calendar_consent" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "custom")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="e4227296-3fbb-0af0-0d38-a3229e8a3931">
|
||||
<Execution id="b84b6463-2659-452e-af58-25dae568993e" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_date_window_translates_on_sqlite_and_keeps_legacy_wall_clock_date" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="e5a658bc-a9ee-f8a6-00da-31a875195d4a">
|
||||
<Execution id="ab124cfe-ea29-4767-bbc0-cf1a26998d80" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Agenda_date_window_translates_on_sqlite_and_keeps_legacy_wall_clock_date" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "include-deleted")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="1ece7e57-e724-aa88-aaa8-6eccd169f3a6">
|
||||
<Execution id="254591dc-0218-4dd0-942c-b80219b885d9" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Rejects_another_owners_job_without_calling_provider" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="2d738780-0c7e-809d-7a36-e22b11e017c3">
|
||||
<Execution id="f7da2a85-8da9-4421-b4dc-9d2bdfaf38db" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Rejects_another_owners_job_without_calling_provider" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "standard")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="5b8ea46d-ee44-6470-1381-3f43ab773db6">
|
||||
<Execution id="de64afe0-b777-4aa4-85b3-352ab2124a14" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.OwnershipGuardTests.Summarizer_service_uses_sha256_cache_key_builder" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="a5089dc5-fff8-aece-6968-d45c244cfd94">
|
||||
<Execution id="303f9c3e-e004-4e14-8007-1ce5761a31dd" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.OwnershipGuardTests" name="Summarizer_service_uses_sha256_cache_key_builder" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Downloads_portable_all_day_deadline_event_without_provider_credentials" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="9634ef4e-56ca-8e7e-717e-86049cac7b6b">
|
||||
<Execution id="f5fe9e01-29d8-4ded-8238-f7eb4ca481d2" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Downloads_portable_all_day_deadline_event_without_provider_credentials" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "interview")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="243583b0-ea8a-0c2d-b704-f9c081502a8c">
|
||||
<Execution id="04dcdb73-32bb-4917-9763-306549743af3" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Creates_follow_up_in_selected_connected_calendar_with_stable_job_context" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="6f507120-70ec-fc23-9a9c-b5662af9e900">
|
||||
<Execution id="8e738f34-9348-40d0-9f05-fc68dfd68f07" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Creates_follow_up_in_selected_connected_calendar_with_stable_job_context" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.ApplicationCalendarControllerTests.Agenda_rejects_unbounded_or_invalid_ranges(from: "2026-01-01", to: "2026-12-31")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="b2951d7e-9ec2-af59-3389-f50ca75dc688">
|
||||
<Execution id="d514a9d8-d74b-4bd5-9d64-b148bd240605" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.ApplicationCalendarControllerTests" name="Agenda_rejects_unbounded_or_invalid_ranges" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "combined")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="84f76a74-2082-ce72-9363-22dca54580d2">
|
||||
<Execution id="e4254dcf-ebe3-4f45-88c3-2a391188fa69" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.RulesEngineProspectTests.A_prospect_is_never_followed_up_or_ghosted_however_old(status: "Preparing")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="b3acf8bc-3ec2-abff-6541-a96daa604534">
|
||||
<Execution id="169c222e-dfc2-4ea2-b7d8-244182df48df" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.RulesEngineProspectTests" name="A_prospect_is_never_followed_up_or_ghosted_however_old" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 2500)" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="1ffc3039-bc58-2cb9-9ee2-3abae47b2e11">
|
||||
<Execution id="04ae9640-c657-4295-bafb-f6bf97e568db" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "location")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="ee747285-6574-0968-3d1b-5b4086b49e77">
|
||||
<Execution id="538a2d14-8e33-4057-9354-b3178af82243" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.RulesEngineProspectTests.An_applied_job_past_the_threshold_still_ghosts" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="92816c05-8654-d3ce-80e3-2a9beb851f21">
|
||||
<Execution id="14f020b3-579b-4ee6-b859-7130a89e982a" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.RulesEngineProspectTests" name="An_applied_job_past_the_threshold_still_ghosts" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page(size: 250)" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="b4d52926-057b-e1a5-2803-210ea3dabd5d">
|
||||
<Execution id="126f9edf-b4a5-4f5b-af4d-26649a2478b0" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Ordinary_table_materialises_correspondence_groups_only_for_the_returned_page" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "needs-work")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="161dc999-3648-3d48-1d7b-99ab066de8f6">
|
||||
<Execution id="4425f5c7-8621-4bfb-af23-f70c346fcb3b" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "correspondence")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="9ca882ec-2b75-a26b-1420-961f41c85538">
|
||||
<Execution id="7544e0ab-5ccc-4bc4-b696-d30d52a00ac7" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.RulesEngineProspectTests.An_applied_job_with_no_applied_date_is_not_ghosted" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="57a70a0d-843e-eb80-0342-f2e1d017491c">
|
||||
<Execution id="2251d469-53c6-429b-af33-9d56fa6895ec" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.RulesEngineProspectTests" name="An_applied_job_with_no_applied_date_is_not_ghosted" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "search")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="63a1c947-a202-ef7f-514d-09b47ec75ee2">
|
||||
<Execution id="7ab77d8d-de8b-448f-b105-2cc93fc4c67f" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "company")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="a8aff3ef-f27a-a882-1aa1-ba9c663cf4ce">
|
||||
<Execution id="0c9e1d5a-c06e-4748-8963-1f712829809f" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "all")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="ebd693de-f8c6-6887-7e1c-635cc17733a8">
|
||||
<Execution id="0be92dbc-c1f5-48b0-a634-41f2d477c653" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
<UnitTest name="JobTrackerApi.Tests.JobQueryParityTests.Table_pages_and_board_have_identical_owned_membership(scenario: "none")" storage="c:\users\connor\.codex\worktrees\direct-roadmap-integration\job tracker\jobtrackerapi.tests\bin\release\net9.0\jobtrackerapi.tests.dll" id="83cff8f8-d781-99e7-95b3-2a039270fd7a">
|
||||
<Execution id="205773aa-d298-451f-b7eb-98d512131040" />
|
||||
<TestMethod codeBase="C:\Users\Connor\.codex\worktrees\direct-roadmap-integration\Job tracker\JobTrackerApi.Tests\bin\Release\net9.0\JobTrackerApi.Tests.dll" adapterTypeName="executor://xunit/VsTestRunner2/netcoreapp" className="JobTrackerApi.Tests.JobQueryParityTests" name="Table_pages_and_board_have_identical_owned_membership" />
|
||||
</UnitTest>
|
||||
</TestDefinitions>
|
||||
<TestEntries>
|
||||
<TestEntry testId="b2951d7e-9ec2-af59-3389-f50ca75dc688" executionId="d514a9d8-d74b-4bd5-9d64-b148bd240605" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="ee88b8e2-383e-d7d0-52bc-8593a0cd45b2" executionId="2da5ddb6-ec56-4225-8854-113af8e1ea0e" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="243583b0-ea8a-0c2d-b704-f9c081502a8c" executionId="04dcdb73-32bb-4917-9763-306549743af3" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="63a1c947-a202-ef7f-514d-09b47ec75ee2" executionId="7ab77d8d-de8b-448f-b105-2cc93fc4c67f" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="04660ada-cf1a-cf8c-ac49-1aa92a2f1595" executionId="e4c86caf-db24-4ceb-9a2f-f30583fc8ef0" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="57096417-b25e-42cc-c6aa-1bf95fed407a" executionId="6cc6c76a-f3a9-4fb9-bebb-2123a43b3194" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="8ee9db5a-f803-b7e2-3c34-baac5edb34c8" executionId="e60af608-3ae0-48a7-968c-1a486811ef70" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="c14f173e-4368-76ea-1308-148f5a610ee7" executionId="981ee887-8fcf-469a-88b1-d94cf7b49665" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="1ffc3039-bc58-2cb9-9ee2-3abae47b2e11" executionId="04ae9640-c657-4295-bafb-f6bf97e568db" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="57a70a0d-843e-eb80-0342-f2e1d017491c" executionId="2251d469-53c6-429b-af33-9d56fa6895ec" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="eb7a20fa-63ab-b655-d3f0-046e269b171c" executionId="6122aa5c-f7a7-4e4a-b413-525ee34367d1" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="a5089dc5-fff8-aece-6968-d45c244cfd94" executionId="303f9c3e-e004-4e14-8007-1ce5761a31dd" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="9634ef4e-56ca-8e7e-717e-86049cac7b6b" executionId="f5fe9e01-29d8-4ded-8238-f7eb4ca481d2" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="e4227296-3fbb-0af0-0d38-a3229e8a3931" executionId="b84b6463-2659-452e-af58-25dae568993e" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="1ece7e57-e724-aa88-aaa8-6eccd169f3a6" executionId="254591dc-0218-4dd0-942c-b80219b885d9" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="b3acf8bc-3ec2-abff-6541-a96daa604534" executionId="169c222e-dfc2-4ea2-b7d8-244182df48df" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="6f507120-70ec-fc23-9a9c-b5662af9e900" executionId="8e738f34-9348-40d0-9f05-fc68dfd68f07" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="e5a658bc-a9ee-f8a6-00da-31a875195d4a" executionId="ab124cfe-ea29-4767-bbc0-cf1a26998d80" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="b4d52926-057b-e1a5-2803-210ea3dabd5d" executionId="126f9edf-b4a5-4f5b-af4d-26649a2478b0" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="c247d002-0f3a-f835-2525-f73d9d342dc3" executionId="28aff3d4-f71f-455b-ab84-285c7ef72cd0" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="2d738780-0c7e-809d-7a36-e22b11e017c3" executionId="f7da2a85-8da9-4421-b4dc-9d2bdfaf38db" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="ee747285-6574-0968-3d1b-5b4086b49e77" executionId="538a2d14-8e33-4057-9354-b3178af82243" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="a75c8efc-b4a8-b8b5-b751-6fee6831ebf4" executionId="de4ad138-c214-4682-a5a3-ec2619064fff" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="ce6f8b56-40b6-78ff-93e6-483db0ceaed8" executionId="e16380b9-dbcc-488b-b5b8-5915895be61d" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="84f76a74-2082-ce72-9363-22dca54580d2" executionId="e4254dcf-ebe3-4f45-88c3-2a391188fa69" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="9ca882ec-2b75-a26b-1420-961f41c85538" executionId="7544e0ab-5ccc-4bc4-b696-d30d52a00ac7" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="3cd2fef8-dfa7-1464-b6a9-026485c0bd9e" executionId="ce1bb01d-b213-4134-b5d5-3732917d69a7" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="1d2f56b0-6892-bc4c-992f-c512e097577a" executionId="17157738-6866-4749-9a3f-d515b3e4cc8e" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="161dc999-3648-3d48-1d7b-99ab066de8f6" executionId="4425f5c7-8621-4bfb-af23-f70c346fcb3b" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="5b8ea46d-ee44-6470-1381-3f43ab773db6" executionId="de64afe0-b777-4aa4-85b3-352ab2124a14" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="a8aff3ef-f27a-a882-1aa1-ba9c663cf4ce" executionId="0c9e1d5a-c06e-4748-8963-1f712829809f" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="4d9cb541-8911-0d74-cb02-8d7f6700dd1f" executionId="eac6efdf-fe15-4f38-bccd-3ed966be3c4c" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="ebd693de-f8c6-6887-7e1c-635cc17733a8" executionId="0be92dbc-c1f5-48b0-a634-41f2d477c653" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="40e20eb7-1334-91dc-68aa-74c908945631" executionId="bcaaca56-6cc7-4649-bf36-48265f9b6957" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="92816c05-8654-d3ce-80e3-2a9beb851f21" executionId="14f020b3-579b-4ee6-b859-7130a89e982a" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestEntry testId="83cff8f8-d781-99e7-95b3-2a039270fd7a" executionId="205773aa-d298-451f-b7eb-98d512131040" testListId="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
</TestEntries>
|
||||
<TestLists>
|
||||
<TestList name="Results Not in a List" id="8c84fa94-04c1-424b-9868-57a2d4851a1d" />
|
||||
<TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />
|
||||
</TestLists>
|
||||
<ResultSummary outcome="Completed">
|
||||
<Counters total="36" executed="36" passed="36" failed="0" error="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="0" inProgress="0" pending="0" />
|
||||
<Output>
|
||||
<StdOut>[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 9.0.19)
|
||||
[xUnit.net 00:00:00.32] Discovering: JobTrackerApi.Tests
|
||||
[xUnit.net 00:00:00.47] Discovered: JobTrackerApi.Tests
|
||||
[xUnit.net 00:00:00.48] Starting: JobTrackerApi.Tests
|
||||
[xUnit.net 00:00:10.61] Finished: JobTrackerApi.Tests
|
||||
</StdOut>
|
||||
</Output>
|
||||
</ResultSummary>
|
||||
</TestRun>
|
||||
@@ -0,0 +1,7 @@
|
||||
# Compact Admin Users actions
|
||||
|
||||
Runtime `171a69089f7d16490b8b12939e0372c423b216cb`. A labelled Actions menu serves both desktop rows and phone cards. It retains role changes, password-reset delivery and deletion with the existing guards and confirmation paths. The final administrator's restricted actions are disabled with an explanation. No factor-recovery control was added.
|
||||
|
||||
The first browser pilots exposed lost focus on confirmation cancellation. The final implementation closes the action menu before opening a confirmation and returns focus after the closing dialog leaves the DOM, provided the trigger remains connected and focus has not already moved elsewhere.
|
||||
|
||||
Passed 14 targeted Jest tests, lint and the export build with TypeScript. The full browser matrix passed 36 configurations with 72 scoped scans and captures. It opens menus with the keyboard, checks final-admin restrictions, restores focus after Escape, and cancels a synthetic deletion confirmation. No mutation or page error occurred. There were 36 unavailable company fixture reads outside Users. The Jest suite retains an existing async test warning. The full server-backed phase 7 suite, live password-reset delivery and native/device review were not run. The phase 7 selectors were updated for the menu.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Compact application row actions
|
||||
|
||||
Runtime `bfbfaeb903705dcbbb78d6ca8f74163d64330994`, from base `70ddee8d` on `codex/a3-ui-10`. Jobs and Trash table rows and phone cards use one named Actions button. The menu reuses the existing edit dialog, status choices, move-to-Trash confirmation and Restore. Active jobs retain the separate workspace link and preparation action. Bulk selection and Kanban keep their existing controls.
|
||||
|
||||
Opening the menu does not navigate to the workspace. Escape and a cancelled move return focus to the row's trigger. The menu is scoped to the visible row and closes when the table/card layout, view or data availability changes. The existing phone and coarse-pointer touch targets are retained.
|
||||
|
||||
The first selected run exposed a stale workflow test assertion from before the accepted “Prepare application” copy change. The refreshed assertions still verify Dashboard, Reminders and Jobs lead to the same tailored-CV route. Table density browser test selectors were also updated for the action menu and explicit selection mode.
|
||||
|
||||
39 selected frontend cases in three suites, full lint and export build with TypeScript passed. The final browser matrix passed 36 journeys and 108 axe scans/captures over nine widths from 320 to 1920 px, English/Bokmål and light/dark themes. It recorded zero console errors, unavailable reads or mutation requests. External Google Fonts requests were blocked in each configuration. The four-configuration pilot overlaps this matrix and is not additional coverage.
|
||||
|
||||
Earlier browser attempts found intermittent document overflow after scrolling and menu focus. The trigger now uses its native title and accessible name, removing the floating tooltip. The final matrix retains the overflow assertion. A separate rerun exposed an asynchronous empty-response test race, corrected by waiting for the response to commit. Failed logs and the overflow screenshot remain alongside the final evidence.
|
||||
|
||||
Browser checks use synthetic reads and cancel confirmations. Unit mocks verify existing status and Restore requests. The server-backed table-density suite was discovered with four cases but was not executed in this increment. Native devices, live mutations and final A3 acceptance remain open.
|
||||
@@ -40,6 +40,8 @@ Owner correction: 3 November 2026. This register extends IM10 and the original 3
|
||||
| V30 | Admin System | Operators cannot tell when the displayed status response last succeeded | RESOLVED in `4981a242` | [Status refresh review](SYSTEM_STATUS_REFRESH_REVIEW.md) qualifies timestamp, stale warning and keyboard retry. Per-signal telemetry remains open. |
|
||||
| V31 | Admin Users | Confirmation lacks an explicit phone label and 2FA status is absent | RESOLVED in `e22f2d64` | [Account status review](ADMIN_USER_2FA_REVIEW.md) covers the read-only flag and aligned presentation. Compact menus and protected recovery remain open. |
|
||||
| V32 | Admin Audit search | The first no-match state clipped its message inside the wide table on phones | RESOLVED in `1a8a97a5` | [Audit search review](AUDIT_SEARCH_REVIEW.md) records the narrow screenshot and fitting feedback. |
|
||||
| V33 | Admin Users actions | Repeated role, reset and delete buttons used most of the action column and phone cards | RESOLVED in `171a6908` | [Admin actions review](ADMIN_USER_ACTIONS_REVIEW.md) covers keyboard menus and final-admin safeguards. |
|
||||
| V34 | Application row actions | Repeated edit, Trash and status controls crowd rows and phone cards | RESOLVED in `bfbfaeb9` | [Application actions review](APPLICATION_ACTIONS_REVIEW.md) covers named keyboard menus, focus, Restore and responsive boundaries. Native and final owner review remain open. |
|
||||
|
||||
The owner-approved design foundation remains original A1 dashboard, D1 visual system, B1 tracking, editor left / preview right, application context right, desktop sidebar and hybrid mobile navigation. No controls, imports, revisions, permissions or provider rights may be removed to obtain visual simplicity.
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
"visualStatus": "FLAT_ROWS_CORRECTED_PENDING_FINAL_VISUAL_REVIEW",
|
||||
"afterStatus": "PASSED:36 configurations /72 title and explicit selection states at 1246994c. Earlier workspace, count, focus and Add Job evidence retained.",
|
||||
"functionalCriteria": "Original preservation register retained; no capability acceptance promotion",
|
||||
"evidence": "APPLICATION_SELECTION_REVIEW.md; evidence/applications-selection/BROWSER.json; earlier APPLICATION_FLAT.md and MATCHING_COUNT_REVIEW.md"
|
||||
"evidence": "APPLICATION_ACTIONS_REVIEW.md; evidence/application-actions/BROWSER.json; earlier APPLICATION_SELECTION_REVIEW.md and APPLICATION_FLAT.md"
|
||||
},
|
||||
{
|
||||
"route": "/jobs/:id",
|
||||
@@ -229,9 +229,9 @@
|
||||
"AdminUsersPage"
|
||||
],
|
||||
"visualStatus": "MEANINGFUL_USER_FORM_TABLE_BOUNDARIES_RETAINED",
|
||||
"afterStatus": "PASSED:36 configurations for read-only 2FA, confirmation and aligned rows or phone cards; creation/dialog/error states remain open",
|
||||
"afterStatus": "PASSED:36 configurations for compact keyboard action menus, aligned rows or cards, 2FA and cancelled confirmation; real delivery and writes remain open",
|
||||
"functionalCriteria": "Original preservation register retained; no capability acceptance promotion",
|
||||
"evidence": "ADMIN_USER_2FA_REVIEW.md; evidence/admin-user-2fa/BROWSER.json; earlier ADMIN_USER_ALIGNMENT_REVIEW.md and ADMIN_HEADINGS_REVIEW.md"
|
||||
"evidence": "ADMIN_USER_ACTIONS_REVIEW.md; evidence/admin-user-actions/BROWSER.json; earlier ADMIN_USER_2FA_REVIEW.md and ADMIN_USER_ALIGNMENT_REVIEW.md"
|
||||
},
|
||||
{
|
||||
"route": "/admin/system",
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"screens": [
|
||||
{
|
||||
"width": 320,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"state": "last-admin-menu",
|
||||
"capture": "focused viewport",
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"width": 320,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"state": "last-admin",
|
||||
"capture": "viewport at top",
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"state": "last-admin-menu",
|
||||
"capture": "focused viewport",
|
||||
"violations": []
|
||||
},
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"state": "last-admin",
|
||||
"capture": "full page at top",
|
||||
"violations": []
|
||||
}
|
||||
],
|
||||
"journeys": [
|
||||
{
|
||||
"width": 320,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"cellOffsets": [],
|
||||
"lastAdminActionsDisabled": "PASS"
|
||||
},
|
||||
{
|
||||
"width": 1440,
|
||||
"language": "en",
|
||||
"mode": "light",
|
||||
"cellOffsets": [
|
||||
{
|
||||
"field": "email",
|
||||
"offset": 0.5
|
||||
},
|
||||
{
|
||||
"field": "userName",
|
||||
"offset": 0.375
|
||||
},
|
||||
{
|
||||
"field": "roles",
|
||||
"offset": 0.5
|
||||
},
|
||||
{
|
||||
"field": "emailConfirmed",
|
||||
"offset": 0.5
|
||||
},
|
||||
{
|
||||
"field": "actions",
|
||||
"offset": 0.5
|
||||
}
|
||||
],
|
||||
"lastAdminActionsDisabled": "PASS"
|
||||
}
|
||||
],
|
||||
"errors": [],
|
||||
"unexpectedWrites": [],
|
||||
"exportDenials": [],
|
||||
"unavailableReads": [
|
||||
"/api/companies",
|
||||
"/api/companies"
|
||||
],
|
||||
"blockedExternal": [
|
||||
"https://fonts.googleapis.com",
|
||||
"https://fonts.googleapis.com"
|
||||
],
|
||||
"limits": [
|
||||
"Every API response is synthetic. In admin-only mode all mutations are blocked and account flows are NOT RUN; otherwise account export is a controlled 403 and confirmations are cancelled.",
|
||||
"Read-only 2FA and confirmation statuses are displayed alongside the existing last-administrator safeguards.",
|
||||
"No real credentials, provider activation, model, native device, integrated security, production or release acceptance."
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 68 KiB |