mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-26 14:52:13 +00:00
docs: amend constitution for capability-first plugins
Signed-off-by: barlind <tobias@barlind.se>
This commit is contained in:
parent
4d046b666d
commit
e76927524a
@ -1,13 +1,28 @@
|
||||
<!--
|
||||
Sync Impact Report
|
||||
Version change: 1.1.0 -> 1.2.0
|
||||
Modified principles:
|
||||
- III. Plugins Are the Extension Point — Isolated by `load_sibling` -> III. Plugins Are the Extension Point — Capability-Declared and Isolated
|
||||
Added sections: None
|
||||
Removed sections: None
|
||||
Templates requiring updates:
|
||||
- [updated] .specify/templates/plan-template.md — Constitution Check now names Slopsmith's concrete gates, including plugin capability declarations.
|
||||
- [reviewed] .specify/templates/spec-template.md — no structural update required; requirements remain feature-focused.
|
||||
- [reviewed] .specify/templates/tasks-template.md — no structural update required; the plan gate drives capability-related tasks.
|
||||
- [reviewed] .specify/templates/checklist-template.md — no structural update required.
|
||||
Follow-up TODOs: None
|
||||
-->
|
||||
|
||||
# Slopsmith Constitution
|
||||
|
||||
> Slopsmith is a self-hosted, single-user web app for browsing, playing, and
|
||||
> practicing interactive music notation, built around its own open `.sloppak`
|
||||
practicing interactive music notation, built around its own open `.sloppak`
|
||||
> chart format (charts imported from Guitar Pro / MusicXML or authored in the
|
||||
> built-in editor). This constitution captures the non-negotiable principles
|
||||
> that govern its core (`server.py`, `lib/`, `static/`) and that all in-tree
|
||||
> plugins (`plugins/<name>/`) inherit by default. It is a *retrospective*
|
||||
> document — the codebase came first, the principles below were distilled from
|
||||
> `CLAUDE.md`, `README.md`, and the shape of the existing implementation.
|
||||
> `AGENTS.md`, `README.md`, and the shape of the existing implementation.
|
||||
|
||||
## Core Principles
|
||||
|
||||
@ -69,28 +84,45 @@ features extend `app.js` and the existing globals (`window.playSong`,
|
||||
layout invariants (`#player` flex-column, `#highway` flex:1,
|
||||
`#player-controls` at the bottom) MUST be preserved.
|
||||
|
||||
### III. Plugins Are the Extension Point — Isolated by `load_sibling`
|
||||
### III. Plugins Are the Extension Point — Capability-Declared and Isolated
|
||||
|
||||
Functionality that is not part of the irreducible "browse + play charts"
|
||||
loop ships as a plugin under `plugins/<name>/`, not as core code. Each
|
||||
plugin is its own directory (typically a separate git repo), discovered
|
||||
at startup via `plugin.json`, and free to add nav links, screens,
|
||||
settings panels, and `/api/plugins/<id>/...` routes. Plugins MUST
|
||||
isolate their backend Python imports via `context["load_sibling"]` so
|
||||
two plugins shipping a generic `extractor.py` / `util.py` / `client.py`
|
||||
do not collide in `sys.modules`.
|
||||
settings panels, and `/api/plugins/<id>/...` routes. Slopsmith-facing
|
||||
plugin behavior is capability-declared by default: manifests describe
|
||||
the domains a plugin owns, provides, requests, observes, validates, or
|
||||
contributes to before any runtime script hydrates. Runtime handlers,
|
||||
legacy wrappers, and private globals are implementation details or
|
||||
compatibility bridges, never the primary integration contract. Plugins
|
||||
MUST isolate their backend Python imports via `context["load_sibling"]`
|
||||
so two plugins shipping a generic `extractor.py` / `util.py` /
|
||||
`client.py` do not collide in `sys.modules`.
|
||||
|
||||
**Non-negotiable rules**
|
||||
|
||||
- Generic features (practice journal, setlist, metronome, tone player,
|
||||
tab view, MIDI control, stem mixing, editors, etc.) belong in a plugin
|
||||
repo, not in `lib/` or `server.py`.
|
||||
- Plugins with Slopsmith-facing behavior MUST declare
|
||||
`standards: ["capability-pipelines.v1"]` plus redaction-safe
|
||||
`capabilities`, `ui`, or `ui_contributions` metadata for the behavior
|
||||
they expose. Metadata-only or transitional manifests that omit
|
||||
capability participation MUST document why no current domain applies.
|
||||
- Runtime participants, event listeners, wrapper hooks, timers, DOM
|
||||
roots, diagnostics contributors, and media nodes MUST be idempotent
|
||||
across repeated script hydration. If a wrapper or private global is
|
||||
still required, it MUST be documented as a compatibility bridge or a
|
||||
missing capability-domain gap.
|
||||
- Plugin backend modules MUST use `context["load_sibling"]("name")` for
|
||||
sibling imports. Bare `import sibling` works during transition but
|
||||
triggers a startup warning when a name collides.
|
||||
- Plugins MUST register routes under `/api/plugins/<plugin_id>/...`,
|
||||
use `window.slopsmith.emit/on` for cross-plugin communication, and
|
||||
prefix their `localStorage` keys with their plugin id.
|
||||
use capability commands/events when an active domain exists, and
|
||||
prefix their `localStorage` keys with their plugin id. General
|
||||
`window.slopsmith.emit/on` events remain acceptable for host events or
|
||||
domains that have not yet been promoted.
|
||||
- Plugins inherit this constitution and may layer additional rules in
|
||||
their own `CLAUDE.md`, but MUST NOT relax core principles (e.g. a
|
||||
plugin cannot require a frontend framework in core).
|
||||
@ -207,11 +239,12 @@ no `..`, no absolute paths).
|
||||
`flex:1`; `#player-controls` sits at the bottom. Hiding the highway
|
||||
collapses the layout — use `margin-top: auto` on controls if you
|
||||
need to hide it.
|
||||
- **Plugin load order**: alphabetical by directory name. The
|
||||
`playSong` wrapper chain runs outermost-first (last-loaded wrapper
|
||||
runs first). Plugins MUST tolerate dependent globals being absent
|
||||
at load time and check at runtime
|
||||
(`typeof window.X === 'function'`).
|
||||
- **Plugin load order**: alphabetical by directory name. Scripts MUST
|
||||
tolerate dependent globals being absent at load time and check at
|
||||
runtime (`typeof window.X === 'function'`). Load order and the
|
||||
`playSong` wrapper chain are implementation details, not integration
|
||||
contracts; plugins declare roles, ownership, compatibility, and UI
|
||||
contributions through capability metadata.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
@ -225,8 +258,9 @@ no `..`, no absolute paths).
|
||||
After pushing a fix, the CodeRabbit loop
|
||||
(`feedback_coderabbit_review.md`) runs to silence.
|
||||
- **Testing**: `pytest` for backend (`requirements-test.txt`),
|
||||
Playwright for browser interactions (`tests/browser/`), CI runs both
|
||||
on every push/PR to `main`.
|
||||
Playwright for browser interactions (`tests/browser/`), and plugin
|
||||
manifest schema validation for capability metadata. CI runs these on
|
||||
every relevant push/PR to `main`.
|
||||
- **CHANGELOG**: every PR updates `[Unreleased]`. Releases rename
|
||||
`[Unreleased]` to `[X.Y.Z] - YYYY-MM-DD` (the VERSION bump itself is
|
||||
automated).
|
||||
@ -246,12 +280,13 @@ no `..`, no absolute paths).
|
||||
explicit constitutional amendment in this file.
|
||||
- Amendments require: (a) a PR that updates this file alongside the
|
||||
code change, (b) an entry in `CHANGELOG.md` under "Migration notes"
|
||||
if user-visible, and (c) a corresponding update to `CLAUDE.md` so
|
||||
AI agents and humans see the same source of truth.
|
||||
if user-visible, and (c) a corresponding update to `AGENTS.md` and any
|
||||
agent-specific imports or instructions so AI agents and humans see the
|
||||
same source of truth.
|
||||
- The principles are listed in priority order. When two principles
|
||||
conflict (e.g. "vanilla frontend" vs. a plugin that wants to ship
|
||||
React), the lower-numbered principle wins by default; the
|
||||
higher-numbered principle's escape hatch is to live in a plugin
|
||||
with its own bundled assets.
|
||||
|
||||
**Version**: 1.1.0 | **Ratified**: 2026-05-09 | **Last Amended**: 2026-06-01
|
||||
**Version**: 1.2.0 | **Ratified**: 2026-05-09 | **Last Amended**: 2026-06-03
|
||||
|
||||
@ -31,7 +31,29 @@
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
[Gates determined based on constitution file]
|
||||
Answer each gate with PASS / FAIL / N/A and a short justification:
|
||||
|
||||
- **Self-hosted Docker path**: Does the feature keep `DLC_DIR` and
|
||||
`CONFIG_DIR` as the only required runtime inputs, with any new
|
||||
dependency installable in the existing Docker image?
|
||||
- **Vanilla/source-served frontend**: Does core remain plain JS and
|
||||
committed CSS, with no framework, runtime CDN/JIT, bundler, or
|
||||
serve-path build step? If plugin CSS is needed, does it ship through
|
||||
`styles`?
|
||||
- **Plugin and capability boundary**: If the feature is outside browse +
|
||||
play CDLC, is it plugin-shaped? Does every Slopsmith-facing plugin
|
||||
behavior declare `capability-pipelines.v1` metadata (`capabilities`,
|
||||
`ui`, or `ui_contributions`) and use `load_sibling` for backend
|
||||
siblings?
|
||||
- **CDLC compatibility**: Are PSARC scanning, sloppak manifests,
|
||||
arrangement IDs, and highway WebSocket messages kept backward-
|
||||
compatible, or is a migration note planned?
|
||||
- **Pure/testable core**: Are new `lib/` helpers flat-importable,
|
||||
side-effect-light, and covered where practical?
|
||||
- **Observability and diagnostics**: Does backend output use logging,
|
||||
and do diagnostics remain redacted and versioned?
|
||||
- **Settings/versioning**: Are settings imports/export paths safe,
|
||||
additive/idempotent, and compatible with the `VERSION` workflow?
|
||||
|
||||
## Project Structure
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- **`highway.getPhrases()` and `highway.getMastery()` public plugin API** — exposes phrase timing windows (`[{ index, start_time, end_time, max_difficulty }]`) and the current mastery slider value (`0..1`) as documented, stable plugin API. Both values were already in memory and reachable via internal names; this surfaces them with intent so plugins can implement section-aware logic (e.g. tracking accuracy per phrase, suppressing difficulty changes during a hard solo) without reaching into undocumented internals. Returns `null` when the song has no phrase data (GP imports, single-difficulty charts). Pair with the existing `hasPhraseData()` to gate phrase-aware code paths.
|
||||
- **Tailwind freshness guard + wider plugin scan.** A new `tailwind-fresh` CI job (`.github/workflows/tests.yml`) rebuilds `static/tailwind.min.css` with the pinned `tailwindcss@3.4.19` and hard-fails on any diff, so the committed prebuilt stylesheet can no longer silently lag source (after PR #411 removed the runtime Play CDN, a stale file shipped unstyled elements with no guard). The `tailwind.config.js` plugin content glob is widened to `./plugins/**/*.{js,html}`, which also scans non-`screen.js` plugin JS (e.g. `plugins/app_tour_*/script.js`) that was previously invisible to the build. Regenerating under the wider glob is a no-op for runtime behaviour — it only adds classes that were already used in source. Groundwork for the plugin `styles` capability (constitution 1.1.0, Principle II): runtime-installed plugins ship their own compiled CSS rather than relying on core's build-time scan.
|
||||
- **Plugin capability pipelines** — adds the first versioned capability coordination layer for plugin authors and support tooling. `/api/plugins` now exposes validated capability declarations, validation warnings, unsupported-version metadata, UI/runtime domain declarations, and compatibility shim summaries for legacy `nav` / `screen` / `settings` / `routes` / visualization surfaces. The browser runtime now tracks manifest participants separately from live handlers, explicit dispatch outcomes (`no-owner`, `no-handler`, `unsupported-command`, `incompatible-version`), claim lifecycle cleanup, manual override precedence, deterministic ownership conflicts, multi-provider ordering, shim hit counts, and a redaction-safe diagnostics snapshot capped at 64 KB. A bundled Capability Inspector plugin shows the live graph, and new docs cover the manifest schema, recipes, safety matrix, lifecycle cleanup, and diagnostics contract.
|
||||
- **Constitution 1.2.0 codifies capability-first plugins.** Principle III now makes `capability-pipelines.v1` manifest declarations the default Slopsmith-facing plugin contract, treats wrappers/private globals as compatibility bridges or capability gaps, and adds a concrete spec-kit Constitution Check gate for plugin capability metadata.
|
||||
- **Audio graph/session capability slice** — promotes `audio-mix`, `audio-input`, `audio-monitoring`, and coordinated `stems` diagnostics into the capability runtime. The new audio session host records song route/fader state, redaction-safe input sources, monitoring lifecycle outcomes, stem automation claims/overrides/orphans, and compatibility bridge hits for legacy faders, song volume, Stems master volume, 3D Highway analyser taps, audio startup barriers, and input source handoffs. `core.audio.session` coordinates `stems` without replacing the Stems plugin as the owner of actual stem playback/state.
|
||||
- **Audio-mix control plane** — makes `audio-mix` the player mixer source of truth. Core now exposes `list-faders`, `get-fader-value`, `set-fader-value`, `inspect-route`, and `inspect-analyser` through the capability runtime, routes native and compatibility-backed fader provider operations with a 2-second timeout, reports committed values back to the mixer UI, suppresses matching legacy faders when a native participant owns the same logical control, and expands audio-session diagnostics/Capability Inspector rendering for fader availability, source modes, bridge hits, route/analyser summaries, and timeout failures.
|
||||
- **Audio-input control plane** — makes `audio-input` the redaction-safe source of truth for instrument input discovery and lifecycle. Core now exposes `list-sources`, `select-source`, `open-source`, and `close-source` through the capability runtime, persists selected logical sources, keeps inspect/list/select prompt-free, routes provider `source.open`/`source.close` operations with bounded outcomes, shares compatible open sessions across requesters, suppresses compatibility-backed duplicate sources when a native provider owns the same logical key, and expands audio-session diagnostics/Capability Inspector rendering for selected input, open sessions, bridge hits, storage status, and permission/device failures without exposing raw device labels or live audio handles.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user