feedBack/docs/plugin-diagnostics.md
Miguel_LZPF 1214a6c0a0
docs: extract plugin contracts into modular docs and slim CLAUDE.md
CLAUDE.md had grown to 545 lines / 50 KB — most of it plugin-author
content that other AI tools (Cursor, Copilot, Codex, Aider) and humans
without AI never reach. Extract the plugin surface into 10 focused
docs and a JSON Schema for plugin.json, then slim CLAUDE.md to a
156-line navigable index.

New docs (~999 lines total, all self-contained):

  docs/PLUGIN_AUTHORING.md            — entry point and quickstart
  docs/plugin-manifest.md             — plugin.json field reference
  docs/plugin-visualization-contracts.md — setRenderer / overlay / note-state
  docs/plugin-audio-mixer.md          — fader registration
  docs/plugin-logging.md              — context["log"] + env vars
  docs/plugin-diagnostics.md          — server_files / callable
  docs/plugin-keyboard-shortcuts.md   — registerShortcut + scopes
  docs/plugin-sibling-imports.md      — load_sibling pattern
  docs/websocket-protocol.md          — /ws/highway message reference
  docs/testing-plugins.md             — pytest fixtures + Playwright

  schema/plugin.schema.json           — Draft 2020-12 schema for
                                        plugin.json; license enum
                                        mirrors CONTRIBUTING's curated
                                        allowlist. Backs CI validation
                                        and the plugin-validate skill.

CLAUDE.md slim (581 lines changed, -485):

  - Removed ~300 lines of plugin-author prose (now in docs/).
  - Kept architecture quick reference, running the app, testing,
    git workflow, versioning, song formats, frontend/backend
    conventions, plugin authoring INDEX (table → docs/), first-hour
    pitfalls, "For AI agents" footer.
  - Anchor stubs preserved next to the new index entries so deep
    links from specs/001-slopsmith-platform/analyze.md still resolve.

Verification:
  python -c "import json,glob,jsonschema; s=json.load(open('schema/plugin.schema.json')); [jsonschema.validate(json.load(open(p)), s) for p in sorted(glob.glob('plugins/*/plugin.json'))]"
  # ok — validates highway_3d, app_tour_library, app_tour_settings
Signed-off-by: Miguel_LZPF <mgcdreamer@gmail.com>
2026-06-18 00:38:50 -07:00

3.6 KiB

Plugin diagnostics contribution

Slopsmith ships an Export Diagnostics feature (Settings → Export Diagnostics) that bundles a redacted set of host + plugin state into a zip the user can share with maintainers. Plugins have three independent opt-ins for contributing to this bundle.

The bundle layout and per-file schemas are documented in diagnostics-bundle-spec.md. This doc covers how plugins integrate.

1. manifest.diagnostics.server_files — opt-in file capture

Declare files under context["config_dir"] to copy verbatim into the bundle:

{
  "diagnostics": {
    "server_files": ["my_plugin.diag.json", "my_plugin_models/active.json"]
  }
}

Rules (same as settings.server_files):

  • Relpaths only. No .., no abs paths, no backslashes, no leading dots.
  • Files land at plugins/<plugin_id>/<relpath> inside the bundle.
  • Encoded as {"encoding": "json", "data": <parsed>} if .json parses cleanly, base64 otherwise.

Use this for snapshot-style state — small DB excerpts, model lists, last-error files. Don't use it for backups (that's settings.server_files).

2. manifest.diagnostics.callable — opt-in dynamic capture

Declare a Python entry point that produces diagnostics at export time:

{
  "diagnostics": {
    "callable": "diagnostics:collect"
  }
}

The form is "<module>:<function>". The module is resolved lazily via load_sibling when the user clicks Export, then called as:

# plugins/my_plugin/diagnostics.py
def collect(ctx):
    """ctx is {"plugin_id": str, "config_dir": Path}."""
    return {
        "schema": "my_plugin.diag.v1",
        "active_preset": _read_active_preset(ctx["config_dir"]),
        "model_count": len(list((ctx["config_dir"] / "models").glob("*.pt"))),
    }

Return-type handling:

  • dict / list → written to plugins/<id>/callable.json
  • bytescallable.bin
  • strcallable.txt

Exceptions are caught and appended to the bundle's manifest.notes — a buggy plugin never crashes the export.

3. Frontend contribution (slopsmith#166)

Plugins that hold useful debug state in the browser (active model name, last user input, internal counters) can push it into the bundle from screen.js:

window.slopsmith.diagnostics.contribute('my_plugin', {
    schema: 'my_plugin.client_diag.v1',
    active_preset: getActivePreset(),
    last_error: _lastError,
});
  • Idempotent. Repeated calls overwrite the previous value.
  • Whatever was last contributed before the user hits Export Diagnostics is what lands in plugins/<plugin_id>/client.json.
  • Available namespace: window.slopsmith.diagnostics.{contribute, snapshotConsole, snapshotHardware, snapshotUa, snapshotLocalStorage, snapshotContributions}.
  • Loaded from static/diagnostics.js ASAP in <head> so the console-wrap is in place before any other script runs.

Best practices

  • Embed a schema field (e.g. "my_plugin.diag.v1") in JSON returned by callable so future tooling can dispatch by version.
  • Keep payloads small (< 100 KB). Diagnostics are not a backup channel — that's settings.server_files.
  • Don't include secrets, API keys, or session tokens. Bundles are shared with maintainers / posted to GitHub issues.