Problem
`knowledge/backends/chromadb_adapter.py:209` returns raw `chromadb.Collection` objects from `list_collections()` — not wrapped in `ChromaDBCollection`. Callers who iterate the returned list and call `.add()` or any other method will bypass the adapter entirely, side-stepping the ABC seam.
Tests pass because they only read `.name` or use `count`, neither of which differs between raw and wrapped. But in production, any consumer iterating to mutate will hit the raw ChromaDB API.
`base.py:174` docstring says "Adapters may return names or objects" which masks this.
Fix
Wrap each returned collection:
```python
def list_collections(self) -> list[BaseCollection]:
return [ChromaDBCollection(c) for c in self._raw.list_collections()]
```
Update the ABC contract to be specific: `list_collections() -> List[BaseCollection]` (drop the `Union[str, BaseCollection]`).
Meta
Found during PR #5129 quality gate review. Must be fixed before any production caller is migrated.
Problem
`knowledge/backends/chromadb_adapter.py:209` returns raw `chromadb.Collection` objects from `list_collections()` — not wrapped in `ChromaDBCollection`. Callers who iterate the returned list and call `.add()` or any other method will bypass the adapter entirely, side-stepping the ABC seam.
Tests pass because they only read `.name` or use `count`, neither of which differs between raw and wrapped. But in production, any consumer iterating to mutate will hit the raw ChromaDB API.
`base.py:174` docstring says "Adapters may return names or objects" which masks this.
Fix
Wrap each returned collection:
```python
def list_collections(self) -> list[BaseCollection]:
return [ChromaDBCollection(c) for c in self._raw.list_collections()]
```
Update the ABC contract to be specific: `list_collections() -> List[BaseCollection]` (drop the `Union[str, BaseCollection]`).
Meta
Found during PR #5129 quality gate review. Must be fixed before any production caller is migrated.