refactor: collapse single-implementation interfaces
Nine interfaces had exactly one implementation and no test double — they existed only to be named twice in a DI registration: IFindingsStore, IFindingsStoreLocator, IPrimeScheduleSignal, IRefineRunner, IWeekReportService, IMergeCoordinator, IMissionControlPane, IOnlineLoginService, ITaskListFilter. Consumers now depend on the concrete type; the DTO records that shared those files moved next to their implementation. IInteractiveLaunchSpecService stays — it carries 54 lines of contract documentation, which is not ceremony. IMergeCoordinator in particular had a redundant null object: MergeCoordinator with a null Handler already no-ops, and every test used the real class with Handler set. Filtering/ collapses from 8 files to 1. ITaskListFilter and TaskListFilterBase were a double abstraction over four predicates, with MatchesAsContext => false declared in both. SmartFlagFilter also compiled its expression twice (its own _flag plus the inherited Matches cache) — it now uses the cache. StaticTokenAuthProvider was in src but production uses ZitadelAuthProvider; it is a test double, so it moves to the test project. Its own test goes away with it.
This commit is contained in:
@@ -4,13 +4,29 @@ using ClaudeDo.Worker.Git;
|
||||
|
||||
namespace ClaudeDo.Worker.Findings;
|
||||
|
||||
/// <summary>One durable finding, as handed in by a caller. Git and DB lookups happen above this layer.</summary>
|
||||
public sealed record FindingInput(
|
||||
string Slug,
|
||||
string Title,
|
||||
string Body,
|
||||
string Scope,
|
||||
string SourceTaskId,
|
||||
string VerifiedAgainst);
|
||||
|
||||
public sealed record SaveFindingOutcome(
|
||||
string Slug,
|
||||
string Path,
|
||||
bool Created,
|
||||
int TotalFindings,
|
||||
bool NearCapacity);
|
||||
|
||||
/// <summary>
|
||||
/// Owns <working-dir>/.claudedo/ — one markdown file per finding plus a rebuilt INDEX.md.
|
||||
/// Pure filesystem: the caller supplies the head commit and source task id.
|
||||
/// INDEX.md is always regenerated from the files on disk, never patched, so findings the user
|
||||
/// deleted or renamed by hand disappear from the index on the next write.
|
||||
/// </summary>
|
||||
public sealed class FindingsStore : IFindingsStore
|
||||
public sealed class FindingsStore
|
||||
{
|
||||
/// <summary>INDEX.md is read by every run; past this many entries it stops paying for itself.</summary>
|
||||
public const int WarnThreshold = 80;
|
||||
|
||||
@@ -3,12 +3,15 @@ using ClaudeDo.Data.Repositories;
|
||||
|
||||
namespace ClaudeDo.Worker.Findings;
|
||||
|
||||
/// <summary>The main checkout a finding belongs to, plus whether its store is committed with the repo.</summary>
|
||||
public sealed record FindingsTarget(string ListId, string ListName, string WorkingDir, bool Tracked);
|
||||
|
||||
/// <summary>
|
||||
/// Maps an MCP call to the project whose findings store it targets. Always resolves to the list's
|
||||
/// WorkingDir — the main checkout — even when the caller runs inside a worktree, because concurrent
|
||||
/// writes into worktree copies would produce INDEX.md merge conflicts.
|
||||
/// </summary>
|
||||
public sealed class FindingsStoreLocator : IFindingsStoreLocator
|
||||
public sealed class FindingsStoreLocator
|
||||
{
|
||||
private readonly TaskRepository _tasks;
|
||||
private readonly ListRepository _lists;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
namespace ClaudeDo.Worker.Findings;
|
||||
|
||||
/// <summary>One durable finding, as handed in by a caller. Git and DB lookups happen above this layer.</summary>
|
||||
public sealed record FindingInput(
|
||||
string Slug,
|
||||
string Title,
|
||||
string Body,
|
||||
string Scope,
|
||||
string SourceTaskId,
|
||||
string VerifiedAgainst);
|
||||
|
||||
public sealed record SaveFindingOutcome(
|
||||
string Slug,
|
||||
string Path,
|
||||
bool Created,
|
||||
int TotalFindings,
|
||||
bool NearCapacity);
|
||||
|
||||
public interface IFindingsStore
|
||||
{
|
||||
Task<SaveFindingOutcome> SaveAsync(string workingDir, FindingInput input, CancellationToken ct, bool tracked = false);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace ClaudeDo.Worker.Findings;
|
||||
|
||||
/// <summary>The main checkout a finding belongs to, plus whether its store is committed with the repo.</summary>
|
||||
public sealed record FindingsTarget(string ListId, string ListName, string WorkingDir, bool Tracked);
|
||||
|
||||
public interface IFindingsStoreLocator
|
||||
{
|
||||
Task<FindingsTarget> ResolveForTaskAsync(string taskId, CancellationToken ct);
|
||||
Task<FindingsTarget> ResolveForListAsync(string listIdOrName, CancellationToken ct);
|
||||
}
|
||||
Reference in New Issue
Block a user