Problem
The eval's Test 23 (Missing Collector Contract) identifies the primary structural gap in the project: there is no formal base class or registration system that enforces the collector contract. BaseCollectorCommand (ref 3) provides a template-method pattern for management commands, but there is no corresponding abstract base for the collector service itself — the thing that actually defines "what a collector must implement." How_to_add_a_collector.md references CollectorBase by name but provides no code scaffold. Contributors must reverse-engineer the pattern from existing apps, risking ad-hoc imports and inconsistent error handling.
Acceptance criteria
- Abstract base class (e.g.,
core/collectors/base_collector.py) defines the collector contract with abstract methods for: collect(), validate_config(), and a name property
- Base class integrates with the existing
CollectorFailureCategory error taxonomy from core/errors.py
- At least 3 existing collector apps are migrated to inherit from the new base class
How_to_add_a_collector.md is updated with a minimal code scaffold showing a complete collector implementation
- Existing tests continue to pass — no behavioral changes
- Tests pass in CI
- PR approved by at least 1 reviewer
Implementation notes
Start with the three most well-tested collectors (likely github_activity_tracker, boost_library_tracker, and one other with good coverage) so regressions are immediately visible. The base class should enforce the write-path convention (service-layer writes only) by design — e.g., the base collect() could accept a service module reference. Keep the contract minimal: the goal is to establish the pattern, not to abstract every collector behavior in week 2. The existing BaseCollectorCommand should delegate to the new base class so the two layers compose cleanly (command → collector → service). Review core/collectors/base.py and core/collectors/command_base.py for the existing abstractions to extend rather than duplicate.
Problem
The eval's Test 23 (Missing Collector Contract) identifies the primary structural gap in the project: there is no formal base class or registration system that enforces the collector contract.
BaseCollectorCommand(ref 3) provides a template-method pattern for management commands, but there is no corresponding abstract base for the collector service itself — the thing that actually defines "what a collector must implement."How_to_add_a_collector.mdreferencesCollectorBaseby name but provides no code scaffold. Contributors must reverse-engineer the pattern from existing apps, risking ad-hoc imports and inconsistent error handling.Acceptance criteria
core/collectors/base_collector.py) defines the collector contract with abstract methods for:collect(),validate_config(), and anamepropertyCollectorFailureCategoryerror taxonomy fromcore/errors.pyHow_to_add_a_collector.mdis updated with a minimal code scaffold showing a complete collector implementationImplementation notes
Start with the three most well-tested collectors (likely
github_activity_tracker,boost_library_tracker, and one other with good coverage) so regressions are immediately visible. The base class should enforce the write-path convention (service-layer writes only) by design — e.g., the basecollect()could accept a service module reference. Keep the contract minimal: the goal is to establish the pattern, not to abstract every collector behavior in week 2. The existingBaseCollectorCommandshould delegate to the new base class so the two layers compose cleanly (command → collector → service). Reviewcore/collectors/base.pyandcore/collectors/command_base.pyfor the existing abstractions to extend rather than duplicate.