docs: correct stale file:line references and the loader-fallback contradiction

CLAUDE.md and .cursorrules disagreed about plugin-directory fallback
behavior; the code (SchemaManager.get_schema_path) probes plugins/
BEFORE plugin-repos/, and the main discovery path has no fallback at
all — both files now describe the real behavior, preferring symbol names
over line numbers so the references rot slower. REST_API_REFERENCE.md
pointed at app.py:144/:607 for mounts that live at :199/:799 and counted
92 routes where there are 94. PLUGIN_ARCHITECTURE_SPEC.md's historical
banner gains a note that its example imports
(src/plugin_system/base_classes/*_plugin.py) never shipped — the real
base classes are src.base_classes.sports.SportsCore and
src.base_classes.hockey.Hockey.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SXb4mKcAkVaxkeTb3YnAdr
This commit is contained in:
Claude
2026-08-05 23:56:15 +00:00
parent ab087cf600
commit 2408309d84
4 changed files with 19 additions and 12 deletions
+5 -5
View File
@@ -3,21 +3,21 @@
## Plugin System Overview ## Plugin System Overview
The LEDMatrix project uses a plugin-based architecture. All display The LEDMatrix project uses a plugin-based architecture. All display
functionality (except core calendar) is implemented as plugins that are functionality is implemented as plugins that are
dynamically loaded from the directory configured by dynamically loaded from the directory configured by
`plugin_system.plugins_directory` in `config.json` — the default is `plugin_system.plugins_directory` in `config.json` — the default is
`plugin-repos/` (per `config/config.template.json:130`). `plugin-repos/` (per `config/config.template.json:167`).
> **Fallback note (scoped):** `PluginManager.discover_plugins()` > **Fallback note (scoped):** `PluginManager.discover_plugins()`
> (`src/plugin_system/plugin_manager.py:154`) only scans the > (`src/plugin_system/plugin_manager.py:208`) only scans the
> configured directory — there is no fallback to `plugins/` in the > configured directory — there is no fallback to `plugins/` in the
> main discovery path. A fallback to `plugins/` does exist in two > main discovery path. A fallback to `plugins/` does exist in two
> narrower places: > narrower places:
> - `store_manager.py:1700-1718` — store operations (install/update/ > - `store_manager.py:2342-2373` — store operations (install/update/
> uninstall) check `plugins/` if the plugin isn't found in the > uninstall) check `plugins/` if the plugin isn't found in the
> configured directory, so plugin-store flows work even when your > configured directory, so plugin-store flows work even when your
> dev symlinks live in `plugins/`. > dev symlinks live in `plugins/`.
> - `schema_manager.py:70-80` — `get_schema_path()` probes both > - `schema_manager.py:48-80` — `get_schema_path()` probes both
> `plugins/` and `plugin-repos/` for `config_schema.json` so the > `plugins/` and `plugin-repos/` for `config_schema.json` so the
> web UI form generation finds the schema regardless of where the > web UI form generation finds the schema regardless of where the
> plugin lives. > plugin lives.
+8 -4
View File
@@ -6,12 +6,16 @@
- `config/config.json` — User plugin configuration (persists across plugin reinstalls) - `config/config.json` — User plugin configuration (persists across plugin reinstalls)
- `plugin-repos/`**Default** plugin install directory used by the - `plugin-repos/`**Default** plugin install directory used by the
Plugin Store, set by `plugin_system.plugins_directory` in Plugin Store, set by `plugin_system.plugins_directory` in
`config.json` (default per `config/config.template.json:130`). `config.json` (default per `config/config.template.json:167`).
Not gitignored. Not gitignored.
- `plugins/` — Legacy/dev plugin location. Gitignored (`plugins/*`). - `plugins/` — Legacy/dev plugin location. Gitignored (`plugins/*`).
Used by `scripts/dev/dev_plugin_setup.sh` for symlinks. The plugin Used by `scripts/dev/dev_plugin_setup.sh` for symlinks. The plugin
loader falls back to it when something isn't found in `plugin-repos/` loader does NOT fall back to it `PluginManager.discover_plugins()`
(`src/plugin_system/schema_manager.py:77`). (`src/plugin_system/plugin_manager.py`) scans only the configured
directory. Fallbacks exist in two narrower places: store operations
(`StoreManager._find_plugin_path()` in `store_manager.py`) and schema
lookup (`SchemaManager.get_schema_path()` in `schema_manager.py`,
which probes `plugins/` *before* `plugin-repos/`).
## Plugin System ## Plugin System
- Plugins inherit from `BasePlugin` in `src/plugin_system/base_plugin.py` - Plugins inherit from `BasePlugin` in `src/plugin_system/base_plugin.py`
@@ -33,7 +37,7 @@
## Skin System (visual overlays for sports scoreboards) ## Skin System (visual overlays for sports scoreboards)
- Skins live in `skins/<skin-id>/` (skin.json + skin.py), NOT in plugin dirs — plugin reinstall deletes plugin dirs - Skins live in `skins/<skin-id>/` (skin.json + skin.py), NOT in plugin dirs — plugin reinstall deletes plugin dirs
- Core: `src/skin_system/` (ScoreboardSkin, SkinContext, runtime); hook: `SportsCore._render_game()` in `src/base_classes/sports.py` - Core: `src/skin_system/` (ScoreboardSkin, SkinContext, runtime); hook: `SportsCore._render_game()` in `src/base_classes/sports/core.py`
- Skins render onto `ctx.canvas` only; fallback to built-in renderer on `False`/exception (3 strikes disables for session) - Skins render onto `ctx.canvas` only; fallback to built-in renderer on `False`/exception (3 strikes disables for session)
- View-model guaranteed keys are frozen (see `test/test_skin_system.py::TestViewModelContract`) — renaming keys in `_extract_game_details_common` or sport extractors breaks published skins - View-model guaranteed keys are frozen (see `test/test_skin_system.py::TestViewModelContract`) — renaming keys in `_extract_game_details_common` or sport extractors breaks published skins
- Validate skins headlessly: `python scripts/validate_skin.py --skin <id>`; docs: `docs/SKIN_SYSTEM.md`, `docs/CREATING_SKINS.md` - Validate skins headlessly: `python scripts/validate_skin.py --skin <id>`; docs: `docs/SKIN_SYSTEM.md`, `docs/CREATING_SKINS.md`
+4 -1
View File
@@ -8,9 +8,12 @@
> - Code paths reference `web_interface_v2.py`; the current web UI is > - Code paths reference `web_interface_v2.py`; the current web UI is
> `web_interface/app.py` with v3 Blueprint-based templates. > `web_interface/app.py` with v3 Blueprint-based templates.
> - The example Flask routes use `/api/plugins/*`; the real API > - The example Flask routes use `/api/plugins/*`; the real API
> blueprint is mounted at `/api/v3` (`web_interface/app.py:144`). > blueprint is mounted at `/api/v3` (`web_interface/app.py:199`).
> - The default plugin location is `plugin-repos/` (configurable via > - The default plugin location is `plugin-repos/` (configurable via
> `plugin_system.plugins_directory`), not `./plugins/`. > `plugin_system.plugins_directory`), not `./plugins/`.
> - Example imports use `src/plugin_system/base_classes/*_plugin.py`;
> the shipped base classes live in `src/base_classes/` (e.g.
> `src.base_classes.sports.SportsCore`, `src.base_classes.hockey.Hockey`).
> - The "Migration Strategy" and "Implementation Roadmap" sections > - The "Migration Strategy" and "Implementation Roadmap" sections
> describe work that has now shipped. > describe work that has now shipped.
> >
+2 -2
View File
@@ -31,9 +31,9 @@ All endpoints return JSON responses with a standard format:
- [Plugin-specific endpoints](#plugin-specific-endpoints) - [Plugin-specific endpoints](#plugin-specific-endpoints)
- [Starlark Apps](#starlark-apps) - [Starlark Apps](#starlark-apps)
> The API blueprint is mounted at `/api/v3` (`web_interface/app.py:144`). > The API blueprint is mounted at `/api/v3` (`web_interface/app.py:199`).
> SSE stream endpoints (`/api/v3/stream/*`) are defined directly on the > SSE stream endpoints (`/api/v3/stream/*`) are defined directly on the
> Flask app at `app.py:607-615`. There are about 92 routes total — see > Flask app at `app.py:799-809`. There are 94 routes total — see
> `web_interface/blueprints/api_v3.py` for the canonical list. > `web_interface/blueprints/api_v3.py` for the canonical list.
--- ---