[Claude, autonomous]
POST /api/merge/sync-harmony returns 200 OK even when the project is blocked from syncing, so the caller can't tell that no sync actually happened.
Root cause
SyncHarmonyProject (backend/FwHeadless/Routes/MergeRoutes.cs) calls SyncWorker.ExecuteSync(onlyHarmony: true) but discards the returned SyncJobResult, then unconditionally returns TypedResults.Ok():
var syncWorker = ActivatorUtilities.CreateInstance<SyncWorker>(services, projectId);
await syncWorker.ExecuteSync(stoppingToken, onlyHarmony: true); // result ignored
return TypedResults.Ok();
ExecuteSync does detect the block and returns SyncJobResult(SyncJobStatusEnum.SyncBlocked, …) (backend/FwHeadless/Services/SyncHostedService.cs), but because the result is thrown away the endpoint still reports success. In the logs the worker logs Project ... is blocked from syncing, and the request immediately finishes 200.
Contrast with the sibling endpoint. ExecuteMergeRequest (/api/merge/execute) checks the same block status up front and returns 423 Locked. sync-harmony should behave consistently.
Impact
The LexBox-side caller FwHeadlessClient.SyncHarmony branches on response.IsSuccessStatusCode. A blocked project returns 200, so the caller treats a skipped sync as a completed one. The sync block is effectively invisible to this code path.
Suggested fix
Map the SyncJobResult to a status code in SyncHarmonyProject (return 423 Locked for SyncJobStatusEnum.SyncBlocked, and surface other non-success statuses like ProjectNotFound / UnableToAuthenticate rather than collapsing them to 200). Extend the response Results<...> union accordingly.
Test: backend/Testing/ApiTests/ProjectBlockingTests.cs is the natural home for a case asserting sync-harmony returns 423 for a blocked project.
[Claude, autonomous]
POST /api/merge/sync-harmonyreturns200 OKeven when the project is blocked from syncing, so the caller can't tell that no sync actually happened.Root cause
SyncHarmonyProject(backend/FwHeadless/Routes/MergeRoutes.cs) callsSyncWorker.ExecuteSync(onlyHarmony: true)but discards the returnedSyncJobResult, then unconditionally returnsTypedResults.Ok():ExecuteSyncdoes detect the block and returnsSyncJobResult(SyncJobStatusEnum.SyncBlocked, …)(backend/FwHeadless/Services/SyncHostedService.cs), but because the result is thrown away the endpoint still reports success. In the logs the worker logsProject ... is blocked from syncing, and the request immediately finishes200.Contrast with the sibling endpoint.
ExecuteMergeRequest(/api/merge/execute) checks the same block status up front and returns423 Locked.sync-harmonyshould behave consistently.Impact
The LexBox-side caller
FwHeadlessClient.SyncHarmonybranches onresponse.IsSuccessStatusCode. A blocked project returns 200, so the caller treats a skipped sync as a completed one. The sync block is effectively invisible to this code path.Suggested fix
Map the
SyncJobResultto a status code inSyncHarmonyProject(return423 LockedforSyncJobStatusEnum.SyncBlocked, and surface other non-success statuses likeProjectNotFound/UnableToAuthenticaterather than collapsing them to 200). Extend the responseResults<...>union accordingly.Test:
backend/Testing/ApiTests/ProjectBlockingTests.csis the natural home for a case assertingsync-harmonyreturns 423 for a blocked project.