feat: plugin model with SourcePlugin ABC, registry, and DataBroker#8
Merged
feat: plugin model with SourcePlugin ABC, registry, and DataBroker#8
Conversation
Introduces the Phase 1/2 plugin architecture from the expansion brief: - plugins/sources/base.py: SourcePlugin ABC with validate_schema() - plugins/sources/__init__.py: REGISTRY dict + @register decorator + load_builtin_plugins() - plugins/sources/lastfm/loader.py: LastFmPlugin wrapping load_listening_data() - plugins/sources/swarm/loader.py: SwarmPlugin wrapping load_swarm_data() - core/broker.py: DataBroker coordinating load, merge, and type availability - tests/test_source_plugins.py: 21 unit tests for schema validation, registry, and both plugins - tests/test_broker.py: 13 unit tests for DataBroker load/merge/query behaviour All 78 tests pass. Non-breaking: visualize.py and analysis_utils.py unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a Plugin System section to the README covering: - Updated project structure tree with plugin directories - Step-by-step guide to creating a SourcePlugin subclass - Required schema columns per plugin type - DataBroker usage example - Updated Contributing section to reference CLAUDE.md and quality gate commands Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
assets/dashboard_mockup.png: high-fidelity mockup rendered with the Deep Space Indigo palette showing sidebar nav, hero card, KPI row, genre streamgraph, top-artists bar chart, pydeck check-in heatmap, and activity calendar heatmap. tools/generate_mockup.py: matplotlib script that regenerates the mockup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes all quality gate failures introduced by the mockup script: - Remove unused imports (matplotlib.patches, FancyArrowPatch) - Remove unused variable ry - Rename unused loop variables to _icon, _i, _bar per ruff B007 - Break long map caption string into a named variable (E501) - Drop unused ax parameter from card() helper; update all call sites - Convert add_axes list literals to tuples (mypy arg-type) - Convert imshow extent list to tuple (mypy arg-type) Also updates CLAUDE.md Section 7 with a mandatory pre-push gate that includes auto-fix steps, a two-stage verify pass, a common failure pattern table, and an explicit rule that no PR should be opened until the full gate passes locally. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This was referenced Mar 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SourcePluginABC withvalidate_schema()and a self-registering@registerdecorator +REGISTRYdictLastFmPlugin/SwarmPlugin(non-breaking wrappers around existinganalysis_utilsfunctions)DataBrokerto coordinate loading, merging, and type-availability queries across pluginsDataBrokerbehaviour; full suite 78/78 passingTest plan
streamlit run visualize.pystill renders all 4 tabs correctly (no behaviour change)🤖 Generated with Claude Code