Skip to content

spec §6: document the client screen contract + normative hot-path rules - #4

Merged
topkoa merged 8 commits into
mainfrom
docs/client-runtime-section
Jul 6, 2026
Merged

spec §6: document the client screen contract + normative hot-path rules#4
topkoa merged 8 commits into
mainfrom
docs/client-runtime-section

Conversation

@topkoa

@topkoa topkoa commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fills the biggest remaining hole: §6 previously said the client runtime API was "out of scope for this version of the spec." This replaces that placeholder with a real, ground-truthed §6 — split into a portable normative layer (safe to pin) and a descriptive layer (Host-provided, Host-versioned, explicitly not frozen by v0.1.0). Traced against the actual Host mount path and runtime objects.

This also gives the best-practices performance guidance (#3) a contract to point at — the "SHOULD NOT do per-frame DOM/IO" rule is now normative in §6.4.

New §6 structure

  • §6.1 Screen mount lifecycle — the Host creates an id-derived container, sources its markup from screen, and executes script once. No Host-invoked entry pointscript self-executes and finds its own DOM by the ids it authored. Normative: re-hydration MUST be idempotent (a second execution installs nothing twice); declaring plugin-runtime-idempotent.v1 asserts this.
  • §6.2 Screen activation and visibility — one screen active at a time; the Host signals transitions; plugins SHOULD react and suspend background work when hidden.
  • §6.3 The client runtime surface (descriptive, not frozen) — the event bus, contribution registries, and the forward-stable capability control plane (capability-pipelines.v1); raw window globals documented as supported-but-legacy and being migrated behind capabilities. No global Host version — per-object version sentinels; feature-detect.
  • §6.4 Performance and the shared main thread (NORMATIVE) — plugin script runs unsandboxed on the ~60fps main thread; SHOULD NOT do per-frame DOM queries / layout reads / IO; MUST NOT subtree-observe a shared container; don't mutate the shell (use contribution registries); suspend loops when hidden; keep state per-instance.
  • §6.5–6.7 — Settings / Styles / Static assets (renumbered from 6.2–6.4; §3 cross-ref fixed).

Design note

Deliberately kept the API shape descriptive (it's evolving — the Host is migrating globals behind capabilities), while pinning only the stable, portable constraints: idempotence, resource discipline, and "prefer registries/capabilities over shell mutation." This documents reality without over-committing an unstable surface.

Scope & checks

spec/plugin-spec-v1.md §6 + examples/full-plugin/README.md pointer + CHANGELOG.md [Unreleased]. No version bump. mkdocs build --strict and check_versions.py pass; no broken anchors.

Merge-order note: touches spec/plugin-spec-v1.md (§6) and CHANGELOG.md [Unreleased], as does #2 (§8). Different spec sections, but expect a trivial [Unreleased] conflict depending on merge order — easy to resolve.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Updated the plugin specification to clarify the client mount lifecycle, screen activation/visibility behavior, and the host-provided, versioned runtime capability surface.
    • Strengthened performance guidance for the shared main thread with hot-path restrictions and lifecycle/idempotent re-hydration expectations.
    • Expanded best-practices for visualization plugins, including per-call renderer factories, per-instance ownership/destroy() cleanup, settings propagation, and failure-safe behavior.
    • Refreshed related changelog and example README references for the latest section numbering and terminology.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c1086ec8-f733-4213-8b43-a80b55651b68

📥 Commits

Reviewing files that changed from the base of the PR and between 712c7e7 and 264781a.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • examples/full-plugin/README.md
  • spec/best-practices.md
  • spec/plugin-spec-v1.md

📝 Walkthrough

Walkthrough

This PR rewrites §6 of the plugin spec, expands the best-practices guide with client-screen and visualization rules, and updates the example README and changelog to match the new section structure and references.

Changes

Client Surface Specification Rewrite

Layer / File(s) Summary
Client surface intro and mount lifecycle contract
spec/plugin-spec-v1.md
Reframes the client surface as Host-versioned, then replaces §6.1–§6.3 with screen mount lifecycle, activation/visibility, and runtime surface rules.
Performance constraints and renumbered sections
spec/plugin-spec-v1.md
Replaces §6.4 with main-thread restrictions and renumbers settings, styles, and static assets to §6.5–§6.7.
Best-practices guide expansion
spec/best-practices.md
Expands the guide with getting started, server route and persistence rules, client-screen performance guidance, visualization renderer contracts, shipping guidance, and publish checklist updates.
README and changelog updates
examples/full-plugin/README.md, CHANGELOG.md
Updates the example README’s spec references and adds changelog entries for the rewritten spec and best-practices sections.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main change: documenting the §6 client screen contract and adding normative performance rules.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/client-runtime-section

Comment @coderabbitai help to get the list of available commands.

@topkoa
topkoa force-pushed the docs/client-runtime-section branch from 712c7e7 to 5d4ca29 Compare July 6, 2026 01:11
@topkoa
topkoa changed the base branch from main to docs/capabilities-real-vocabulary July 6, 2026 01:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@spec/plugin-spec-v1.md`:
- Around line 263-269: The re-hydration guidance currently uses a process-wide
singleton guard, which can block later screen instances. Update the wording
around the plugin `script` idempotency rule and the
`plugin-runtime-idempotent.v1` standard so the no-op check is scoped to a
mounted container or per-screen runtime token rather than a module-global
global, keeping the guidance consistent with the per-instance behavior described
in §6.4.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3572023d-2199-4fe4-abae-d07902e44ca0

📥 Commits

Reviewing files that changed from the base of the PR and between 6bc1f30 and 712c7e7.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • examples/full-plugin/README.md
  • spec/plugin-spec-v1.md

Comment thread spec/plugin-spec-v1.md

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces the §6 “client runtime API is out of scope” placeholder with a structured client-screen contract: a normative, portable layer (idempotence + performance/resource-discipline rules) plus a descriptive, Host-versioned runtime-surface description, and updates docs/changelog references accordingly.

Changes:

  • Rewrites spec/plugin-spec-v1.md §6 to document screen mount lifecycle, activation/visibility signaling, the Host-provided runtime surface, and normative shared-main-thread performance rules.
  • Updates the full-plugin example README to link to the new §6 anchors and clarify which parts are normative vs Host-versioned.
  • Adds an [Unreleased] changelog entry summarizing the §6 rewrite and section renumbering.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
spec/plugin-spec-v1.md Replaces §6 placeholder with detailed screen lifecycle + runtime surface description and normative performance rules; renumbers §6.5–6.7.
examples/full-plugin/README.md Updates spec links to new §6 structure (mount lifecycle, runtime surface, performance rules).
CHANGELOG.md Documents the §6 rewrite and renumbering under [Unreleased].

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread spec/plugin-spec-v1.md Outdated
Comment thread spec/plugin-spec-v1.md Outdated
Comment thread spec/plugin-spec-v1.md Outdated
topkoa and others added 2 commits July 6, 2026 00:22
Replace the "client runtime API is out of scope" placeholder in §6 with a real,
ground-truthed contract, split into a portable normative layer and a descriptive
(Host-versioned, not-frozen) layer.

- §6.1 Screen mount lifecycle: Host creates an id-derived container, sources its
  markup from `screen`, and executes `script` once. There is NO Host-invoked
  entry point — `script` self-executes and finds its own DOM. Normative:
  re-hydration MUST be idempotent (a second execution installs nothing twice);
  declaring plugin-runtime-idempotent.v1 asserts this.
- §6.2 Screen activation and visibility: one screen active at a time; the Host
  signals transitions; plugins should react and suspend background work when hidden.
- §6.3 The client runtime surface (descriptive, explicitly not frozen): the event
  bus, contribution registries, and the forward-stable capability control plane
  (capability-pipelines.v1); raw window globals documented as supported-but-legacy.
  No global Host version — per-object `version` sentinels, feature-detect.
- §6.4 Performance and the shared main thread (NORMATIVE): SHOULD NOT do per-frame
  DOM queries / layout reads / IO; don't observe or mutate the shell (use
  contribution registries); suspend loops when hidden; keep state per-instance.
  This anchors the best-practices performance guidance in the contract.

Renumber Settings/Styles/Static-assets to §6.5–6.7 and fix the §3 cross-ref.
Update the full-plugin README pointer and CHANGELOG [Unreleased].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: K. O. A. <topkoa@gmail.com>
…ctive-screen)

- §6.1: drop misleading §6.4 cross-ref on identifier namespacing; namespace under id.
- §6.1: clarify the re-hydration guard suppresses global side effects, distinct
  from per-instance screen state.
- §6.4: spell out 'blocking I/O or network I/O' with a localStorage example.
- §6.4: reword to 'mount more than one instance of a screen' so it doesn't
  contradict §6.2's one-active-screen statement.

Signed-off-by: K. O. A. <topkoa@gmail.com>
@topkoa
topkoa force-pushed the docs/client-runtime-section branch from 5d4ca29 to 145a383 Compare July 6, 2026 04:24
topkoa and others added 4 commits July 6, 2026 00:24
Add a "Client screen & the shared main thread" section to the best-practices
guide, grounded in real feedBack performance regressions rather than generic
advice. The screen runs unsandboxed on the same main thread as a ~60fps note
highway, and most historical plugin perf problems came from that.

New rules:
- Never do DOM queries / layout reads / style writes on a per-frame or
  high-frequency path (rAF, draw(), short setInterval, MutationObserver) —
  resolve refs once on mount; batch reads then writes. (A profiled lag report
  was three plugins each doing a per-frame querySelectorAll.)
- Don't DOM-observe or mutate the app shell — especially the song/library cards.
  Contribute UI via the Host registration APIs; no subtree MutationObserver on
  shared containers; keep per-item predicates O(1). (Replaces the legacy
  .song-card DOM-observation pattern.)
- No synchronous localStorage / await fetch on a hot or gameplay-event path.
- Make re-hydration idempotent (plugin-runtime-idempotent.v1) with a stable
  window singleton; a second script run must be a no-op.
- Stop rAF loops / event subscriptions when hidden; keep state per-instance
  (splitscreen runs multiple instances).
- Reach other plugins via capability claim/dispatch/release, not their globals.

Regroup the guide (Getting started / Server routes / Client screen / Shipping)
and expand the pre-publish checklist with a client-performance block. Docs only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: K. O. A. <topkoa@gmail.com>
Rule 11 + checklist: distinguish synchronous localStorage from awaited network
I/O; fetch itself is asynchronous.

Signed-off-by: K. O. A. <topkoa@gmail.com>
Add a "Visualizations" section to the best-practices guide for
type: "visualization" plugins, ground-truthed against the Host's renderer
contract and the recent splitscreen/settings fixes.

- Factory pattern (rule 15): window.feedBackViz_<id> MUST be a factory function
  returning a fresh renderer per call — this is what makes splitscreen's N
  simultaneous panels work; a singleton shares one context/canvas/meshes across
  panels and collides. Includes the renderer interface (draw required;
  init/resize/destroy/contextType/readyPromise optional) and lifecycle.
- Per-instance resources + destroy() cleanup (16); read-only per-frame bundle,
  allocation-free draw() (17); self-detect canvas size drift (18).
- Settings communication (19): declare `settings` on the visualization
  capability and implement applySetting(key, value) on the instance — the Host
  applies each change to the specific per-panel instance (inherently per-panel).
  Documents the concrete failure modes recent fixes addressed: apply-live-never-
  reload, no cross-setting leakage (backfill once, don't mirror on read),
  deliberate per-panel vs global key scoping, fan-out to all panels, and the
  settings panel loading before the renderer.
- Fail-safe auto-revert (20): guard draw() or the Host reverts to default after
  repeated throws.

Renumber the Shipping section to 21-25 and add a Visualizations checklist block.
Docs only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: K. O. A. <topkoa@gmail.com>
… (rule 19)

Rule 19 said "the Host owns persistence" but never addressed localStorage. Make
it explicit: prefer Host-owned persistence (declare the setting, apply live, let
the Host store/replay) and do not hand-roll settings into localStorage — that is
what keeps export/import and backups whole and stops per-panel copies drifting.
For a self-managed viz that predates the contract, add the quota-safe rule from
the fixes: localStorage is synchronous and can throw (quota / private mode), so
stage the value in an in-memory fallback before setItem and prefer it on read,
and never touch localStorage on a per-frame path. Add a matching checklist item.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: K. O. A. <topkoa@gmail.com>
Base automatically changed from docs/capabilities-real-vocabulary to main July 6, 2026 04:41
topkoa added 2 commits July 6, 2026 00:42
best-practices: client hot-path performance guidance
…tions

best-practices: Visualizations (factory pattern + per-instance settings)
@topkoa
topkoa merged commit 07009e3 into main Jul 6, 2026
7 of 8 checks passed
@topkoa
topkoa deleted the docs/client-runtime-section branch July 6, 2026 04:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants