My systems work on components without needing to now anything about entities. I want to implement simple grid partitioning, so each entity will be given a cell based on its current position. But how will systems know which components to update and how? For example: CollisionSystem must check collision between each components within a cell, but CollisionComponents must be somehow attached to the grid for system to know what collision to test, which doesn't seem like a good solution. What should I do?
Artificial intelligence components (for example) must know the state of the world in order to make decisions: There is nothing inherently wrong with letting a component have access to outside world state.
However, collision detection is typically (not always) handled by a function that sits outside of the elements to be collided. This is a matter of scope / context. In order to reduce coupling, which seems to be your intent, it is better to have one of the supersystems which already have access to all entities (bodies), apply the collisions. This prevents entities from having to know about one another, and it also allows fine control over the ordering of collision detection and resolution, which is crucial.
So, you have your game loop. Somewhere in there you have a phase where you're processing collision detection and resolution. The wise choice would be to factor that out either into a separate function or even a whole separate class, depending on your language and architectural preference.
Given that you desire spatial partitioning over your world space, I would suggest implementing a discrete class
CollisionManager. Therein, create your partitioning structure. You could add / remove entities to
CollisionManager at creation / expiry of those entities, and most importantly, call
CollisionManager.update() on each global update, ensuring that everything -- both moving between partitions (based on entity translations performed just prior via other subsystems) and testing for and resolving collisions within partition locales -- is resolved compactly via a single method call.
As for your entity components associated with physics, the only purpose they serve here is to supply their respective positions and bounds information to