a) If we also introduce domain services that don't represent domain concepts, but instead only control the granularity, don't we introduce non-domain concept into domain? If so, doesn't that hurt domain model?
While the services don't introduce any new behavior into the domain, they don't introduce non-domain concepts either. I view these services, application services specifically, as providing an encapsulating role for the domain - a facade. Each method on the service represents a domain use case and it delegates directly to domain objects. This makes it much easier for clients of the domain layer, since they don't need to worry about coordinating repositories and calling suitable behavioral methods on aggregates. Instead, they invoke a method on the application service.
b) Should most of communication with upper layers be done through medium-grained domain objects? Thus, for every use-case where communication happens through fine-grained domain objects we should introduce medium-grained domain service(s)?
Outer layers should call application services, which in turn delegate to aggregates or domain services. Note, application services are different from domain services. An application service can fully encapsulate the domain such that no domain objects are exposed by its interface, instead relying on DTOs to pass messages between outer layers and the application service. In addition to protecting the domain, this provides an opportunity to utilize something other than a domain model to implement use cases, such as a transaction script.
What coding conventions is he referring to?
One convention can be the presence of Application in service name, such as CargoApplicationService. Another convention is to place application services, which BTW can also be implemented as command handlers, into an Application module within the project.
EDIT
Take a look the this project on GitHub which implements the domain discussed in the book in a modern C# style.
UPDATE
With regards to granularity, a domain service serves a similar role to an application service. IMO, it is a matter of preference whether the application service exists in a separate application layer project or together with other domain objects. Creating an additional barrier between an application service and domain objects can become a needless abstraction. The application service does a fine job of preventing knowledge leaks and in some sense, that is its central job.
UPDATE 2
a) I was talking about domain services in general, because they all tend to increase granularity beyond entities and VOs.
b) Yes, because it still captures a domain concepts, namely use cases which are less granular then the domain objects used to implement them. Sure the application service has concerns largely orthogonal to the domain, but there isn't always a reason to put them into different layers.
c) Yes, but you can't get around leaking domain knowledge all together. If you have a database table with a name Customers which corresponds to the Customer entity, you have domain knowledge leaked into database. The point isn't to prevent all leaks, but to instead create boundaries around areas of cohesion, such that when making changes, they can be isolated to a specific layer.
d) Application service creates a facade around domain objects, effectively establishing a barrier so that clients of the domain, other than app service, have a clean interface to work with. In this way, app service is an "exception", because it sits between domain objects and outer layers.