Rifflet Common Framework (RCF)
Start with [Canonical Rifflet Spec 2.15.0](CANONICAL_RIFFLET_SPEC.md) and [Content Onboarding](CONTENT_ONBOARDING.md). Describe every published edition in the validated catalog metadata; record its actual permissions, services, genres and intended audience. Legacy full-spec conformance is not implied by metadata normalization.
The Rifflet Common Framework (RCF) is the shared runtime, entry/navigation, lifecycle, Menu, identity, feedback, sharing and measurement contract. Its existing module and wire-schema versions remain independent of the product name and canonical spec. It is not a separately published npm SDK or a public upload service.
Plain static web modules are the common substrate. Native HTML controls, CSS and optional Canvas/Web Audio allow distinct experiences without forcing all three into one visual template. Reuse existing CRAVE media and recipe records where relevant; do not duplicate the full old studio. No dependency installation is required to build or preview.
Directories and public mapping
apps/<slug>/→dist/<slug>/: owned app code and explicit public assets.shared/→dist/shared/: runtime primitives and optional design tokens.shell/→dist/: gallery and desktop mobile viewer.scripts/: local build, manifest validation, preview and tests, never public.coordination/,references/, docs and QA: never published.
Each app imports ../../shared/runtime.js in source. Browser resolution from /<slug>/ reaches /shared/runtime.js. Use relative paths for app media. The build preserves app source, injects deployment metadata, and versions local module/style URLs in dist. Riff migration can package app + shared assets beneath a base path; do not hard-code demos URLs in functionality.
Runtime exports (frozen v0.1 contract)
createRuntime({id, version}) returns:
readState(defaults, validators): read only recognized query parameters with per-key validation.share(state): native share or clipboard/manual fallback; returns{method,url}. User gesture required.remix({title, state, instructions}): open the common riff-idea request. This submits an explicitly consented public request; it does not generate an app or satisfy the actual maker loop.emit(type, detail={}): bounded local memory events with timestamp and ID/version. Do not put free text or personal data in detail. The optional internal-test analytics bridge receives the local event then retains only centrally reviewed scalar details. It translates analytics.json semantic mappings and collects automatically without disclosure UI. See ANALYTICS.md; normal builds keep collection disabled.exportFeedback(feedback): the low-level helper still downloads local feedback/events JSON. In the built UI, legacy export-review/feedback buttons are intercepted by the common menu for explicit public submission. Receipt export is a separate recovery/removal action; automatic event telemetry is not submitted.sound.enabled,sound.toggle(),sound.tone(frequency, duration): gesture-unlocked Web Audio; sound enabled by default.reducedMotion: initial media preference. Apps must also listen for preference changes when animating.save(state),restore(fallback): app/version-scoped local storage with graceful failure.
Text, timer/recipe data, interaction state and captions must be independent of media. A sensor is an optional input adapter; never the sole way to act. App-level simulation must be clearly distinguishable from footage or scientific/kitchen validation.
Manifest and integration
Every app has a static content.json. Build validates required metadata and local entry file and generates /catalog.json for agent discovery. Only apps marked draft-ready or reviewed appear in the public gallery. Status describes implementation; peer reviews and QA are separate evidence. Only trusted, reviewed local scripts are included; this is not an arbitrary-code hosting platform.
Source control
Staging is a new local Git repository because its parent has no Git repo. main is Codex's integration branch. Agents use disjoint owned folders in the current checkout during bootstrap and do NOT switch branches or stage others' files. For later independent work, use git worktree add ../staging-<agent> -b agent/<agent>/<topic> from a clean checkpoint. Coordination remains in the canonical staging folder. Submit commit hash and changed paths; Codex cherry-picks after review. No force pushes, secrets, broad git add ., or automatic remote creation. This initial repo has no remote until one is chosen.
Release and rollback
Codex builds, tests, inspects public file list, commits explicit paths, then deploys dist/ to one Cloudflare Pages project. Paths give riff.marantz.net/<slug>/ without one DNS record per app. Keep last-good Pages deployment URL/hash and source commit in HOSTING.md. Roll back through Pages deployment controls; never overwrite other domains. Unknown service spend means stop, not accept a plan upgrade.
Validated manifest shape
schemaVersion is the string "0.1"; version is SemVer; id must equal the kebab-case folder name. title, creator, summary, interaction, and completionEvent are nonempty strings. audience and modalities are nonempty arrays of strings; permissions is an array of optional permission names (empty if none). durationSeconds is a positive finite numeric estimate, not a measured result. entry is index.html. provenance and remix are objects. status is draft, draft-ready, or reviewed; only the last two publish. Extra provenance fields are preserved.
See scripts/manifest.mjs for executable validation and apps/crave-lab/content.json for a complete example. Invalid metadata fails before replacing the previous build. Tests, fixtures, hidden files, private directories and backend entrypoints are excluded from dist. Vendored libraries must carry their license; LICENSE and LICENSE-<library>.txt files are included, while arbitrary text notes remain private.
PUBLIC_ORIGIN=https://riff.marantz.net npm run build injects canonical/og:url and makes existing og:image URLs absolute in output HTML only. Local source stays portable. Do not hard-code the temporary host in app state or asset paths. An origin is not a base path; Riff base-path packaging is a future contract item.
Runtime and asset provenance
Plain web APIs are the shared foundation; individual apps may vendor a reviewed library when their modality needs it. Jumpscare uses a lazy-loaded local Three.js module with its MIT notice, not a remotely hosted script or a new service. The public build remains dependency-install-free. Spatial audio is app-owned for this MVP; host-wide audio and motion adapters are explicit Riff asks, not implemented SDK features.
Recipe apps reuse the same canonical pancake record ID/version. Their local recipe.json files are deployment copies; source ingredients, quantities, steps, yield and untested flags must agree. A different illustration or experience does not authorize changing recipe facts. Update the upstream record deliberately, then refresh both deployment copies and recheck scaling.
Release cache identity
The build fingerprints the complete public output and writes physically versioned local script/style filenames and rewrites local script/style entries, literal ES-module imports (including lazy imports), and CSS imports. Changed shared dependencies therefore invalidate their unchanged importers too. Source, media URLs, navigation and canonical/share links stay unchanged. Use literal relative module specifiers; computed imports cannot be versioned statically. Tests cover unchanged rebuild stability, dependency changes and source preservation.
The custom demos domain was observed returning a four-hour JavaScript browser TTL while HTML/catalog revalidate. _headers requests revalidation, but versioned module graphs provide fresh code even when the existing zone policy overrides JS lifetime. No unrelated zone setting is changed. A global public-output fingerprint trades a little repeat-download efficiency for a coherent review release. If replacing media at an existing URL, use a new filename; media URLs are deliberately not rewritten.
Data-only Rifflets (round 4)
A source release and a personalized instance are different objects. shared/rifflet.js uses the bounded, hashed instance contract in shared/rifflet-core.js. A child carries one immediate parent reference, not an unbounded chain. Hashes detect accidental changes; they are not signatures, identity verification, or protection against someone editing client-side data.
The build emits shared/source-releases.json with a full Git commit only when public source and build scripts are clean. An uncommitted preview can play, but the shared adapter refuses to mint a falsely attributed release. Private coordination notes do not block source pins. Commit source before the final build; never hard-code a pretend hash.
Apps supply exact field validation, authored preset bounds, and any semantic checks (for example, unique puzzle solutions). readRiff rejects invalid or oversized input before applying it. shareRiff exposes a selectable URL before trying the native share sheet, with clipboard/manual fallbacks. Do not pass its payload through the older runtime's 512-character state fields.
Historical links preserve their data and release reference; the current page does not replay historical source automatically. Show a release-drift notice when appropriate. Feedback is an explicit local JSON download, with no automatic collection and no engagement claims.
Recipient and derivative semantics
Forwarding unchanged content preserves its identity and generation. Restarting a riff keeps its parent unless the user explicitly chooses a labeled fresh start. Explain what changed; an audience-only change should not imply different underlying game outcomes. Previews preserve the challenge without exposing its solution. Compact arrival screens may fold secondary comparisons while keeping provenance and important warnings visible. See AGENTS.md and the Round4 peer-review dispositions.
During asynchronous restoration, visible authoring controls must remain non-accepting until state is ready. Rendering must derive hidden and disabled states from the same current state, not stale DOM flags. Verify the first action after startup, entering a riff and restarting a riff in an actual browser, including delayed module loading. Unit-level readiness checks alone cannot establish UI behavior.
Optional persistence and loading are failure boundaries. Browser storage getters may throw before any getItem call; keep the in-memory experience usable. Preserve old version-key saves during migration. A stalled optional module needs a bounded fallback, and a late response must not reset authored state. Reject a release record that disagrees with the running app identity/version instead of emitting a mislabeled riff.
Round 5 integration lessons
A pending native share must not trap authoring. Display the manual URL first, keep a usable exit, and invalidate stale completion callbacks when the draft changes; an old promise must not announce or overwrite a newer link. Reproduce maker re-entry and cancellation while sharing is unresolved.
Simulation time must survive variable frame cadence: preserve fixed-step remainders, bound pause catch-up, and verify scheduling at60/120/144Hz in addition to engine tests.
Study builders explicitly requested by the user may serialize bounded public questions and answers. Explain that link text is public; exclude private data, ratings and progress. This exception does not authorize puzzle-solution spoilers or personal rosters. These expectations extend AGENTS.md and originate in independent Block Party/Pocket Putt reviews and the user's flash-card brief.
Common feedback, riff history and mobile menu (hosted pilot)
Hosted on https://riff.marantz.net/ with the user-authorized existing Cloudflare plan. Production feedback retry, history readback and removal, plus child/grandchild riff publication, were verified September 30, 2026 at source 191ad23d2a17f1c35b3402d7894e24574e409249. Automated test entries were removed; these checks are not human engagement evidence. Use the common bottom-right Menu for feedback, ideas, history and making a version. At widths up to 700px the viewer uses the full viewport; audited branding moves as original nodes into About in the flyout, while instructions, first actions, warnings and game controls stay inline. Opening or closing the menu must preserve play state and return keyboard focus. Do not clone IDs/listeners or replace working controls with raster UI.
Feedback categories are feedback, bug, feature and riff-idea. Show app ID, release version/commit and optional instance/parent IDs before explicit public consent and submit. No automatic telemetry, sensor frames, microphone recordings or identifying fields are attached. The text and displayed context become public lab history; do not include private information. Actor labels are self-reported human/agent-test/unknown, not verified identity or engagement.
Keep drafts locally when storage is available. Submit only on user action; pending means not confirmed delivered. Manual retry reuses the same submission ID, body and deletion capability. Download/import a private receipt to retry or remove an entry; its removal key must never enter a shared URL. If storage is denied, keep the current text and offer receipt export rather than claiming persistence. Acknowledgement, not a local save, changes the item to received.
Little Safe, One-Minute Town, Block Party, Pocket Putt, Recall Studio and Memory Palace have actual maker editors. The experimental Skeleton Lens also has a bounded challenge editor; its simulated hand/wrist model is not an anatomical validation or body-tracking claim. Other Make a riff actions open a real riff-idea request, not an automatic generator or copied prompt. A prepared validated riff can be published to public lab history only after a separate explicit checkbox. All authored settings become public, including Recall questions and answers; play progress does not. Preserve source release and recorded parent, without claiming verified parent authorship or observed lineage. Public payloads remain until removed or the pilot ends. A private receipt enables removal; minimal tombstones prevent replay and platform backups may retain prior data. The pilot caps lifetime submissions at 5,000 including tombstones and limits each IP/hour to 20 mutations and 120 reads. These are abuse controls, not a zero-cost guarantee. The user authorized enabling hosted feedback on the existing paid plan; unrelated new spend still requires approval. See server/README.md for the exact API and failures. Acceptance requires keyboard/touch reach, preserved play, offline and denied-storage recovery, exact retries, public readback and receipt-based removal. Owner triage and reviewed release linkage remain required operational follow-through.
Maker brief and explainable discovery contract
Publication maturity is explicit: playable content, saved-state sharing, a collected riff request, and an implemented content editor are distinct capabilities. For each new editor, the coordinator must register the app's pure semantic validator with the hosted feedback API and verify valid/invalid content and lineage at the server boundary before advertising public riff publication. Browser-only validation does not satisfy this gate.
Optional capture/sensor capabilities require route-specific host and iframe policies plus direct-route and embedded-viewer checks. Do not grant camera access to unrelated apps. A simulated camera background, device-tilt rotation and body tracking are different features; name only the behavior implemented and tested.
Product alignment: maker brief → review → approved/editable taste → explainable match → play → human feedback → revision. This describes the intended pipeline. Local catalog generation, explicit discovery filters and deliberate event downloads implement only parts of it; centralized review, taste storage and matching from behavior are not integrated. Public feedback and history are deployed and verified; operational triage remains manual.
The coordinator generates catalog[].makerBrief from existing content metadata plus shared/discovery.js; app owners keep the established content.json schema. catalog[].discovery carries the controlled classification. getDiscovery(content) returns null for unknown classifications and inherits the parent mapping for creator variants. Do not silently fill unknowns with guessed interests. Schema and field names:
{
"schemaVersion": "rifflet.brief/0.1",
"appId": "app-slug",
"title": "Maker title",
"creator": "Declared creator",
"what": "What the experience does",
"whoFor": {
"interests": ["puzzles"],
"contexts": ["beginners"],
"declaredAudience": ["Maker's audience description"],
"reason": "Why this activity suits that audience",
"basis": "maker-declared"
},
"experience": {
"interaction": "Meaningful actions and payoff",
"modalities": ["visual", "touch and keyboard"],
"estimatedDurationSeconds": 120,
"completionEvent": "app_specific_completion"
},
"source": {"version": "0.1.0", "commit": null},
"review": {"publicationStatus": "draft-ready", "platformReview": "not-integrated"},
"permissions": [],
"provenance": {},
"remix": {}
}
The example is illustrative, not a valid release pin. source.commit is the full immutable commit when known; null remains explicit for an unpinned preview. Duration is an estimate, audience is maker-declared, and local publication status does not mean the Riff platform reviewed the work. Preserve permissions, provenance and remix metadata rather than replacing them with an approval claim.
Controlled interests: puzzles, music, food, languages, nature, creativity, calm, arcade, mystery. Separate audience contexts: beginners, curious-learners, makers, groups. A “Good for” rationale comes from this declared mapping. A match explanation names the user's explicit local filter and the relevant brief property. It must not claim the visitor has a history, cohort membership or inferred taste. Local filter choices neither authorize tracking nor implement the proposed approved taste-note service. That future service needs approval before use, inspection/edit/delete and explicit separation of declared taste from any separately consented behavioral evidence.
A content instance may change audience, purpose or intended use even when the source code is unchanged. Current catalog makerBrief describes the base app release only. A future publish adapter must derive an instance-specific brief from validated authored data and retain immutable parent/source identity; it must not silently inherit the parent’s whoFor, intent or review approval. Review the changed content/intent with its own brief revision. Until implemented, a personalized link is not evidence that its derivative audience was classified, matched or approved.
Designed behavioral evidence pipeline, separate from explicit feedback
Normalize future records to these event names while retaining an app's reviewed meanings: started, milestone, completed, share-attempt, link-copied, recipient-open, riff-created, skip. started is a meaningful user start, not an impression. milestone records an intermediate achievement and keeps the attempt open. completed is reserved for finishing the full defined experience; open-ended apps declare no final completion. share-attempt records intent; link-copied requires confirmed clipboard success and does not imply sending. recipient-open requires observing the recipient opening the specific shared experience; never infer it from a sender's click or copy. riff-created requires a validated new derivative, not an unchanged forward. skip requires an explicit skip action; abandonment, timeout, hidden tab and close are not skip.
Designed event context: schema version, unique event/idempotency ID, timestamp, event name, actor (human, agent-test, unknown), app ID, code version/full release commit when known, optional bounded instance/parent IDs, surface and minimal bounded outcome context. Actor is a backward-compatible declaration. Private reports separately classify likely visitor, agent, registered internal test or unknown from bounded evidence and preserve unknown when evidence is insufficient. This does not verify a person. App-local event names need the reviewed rifflet.analytics/0.2 adapter.
Explicit public feedback and riff registration use the separate consented contract above; they are not behavioral analytics. The October 2 hosted invited-test analytics service and creator obligations are defined in [ANALYTICS.md](ANALYTICS.md), with an automatic internal-test SDK, separate private collector (including trusted IP/device diagnostics) and private dashboard/raw evidence export. Normal builds remain disabled. It measures running app releases only; verified recipients, derivative attribution and creator self-service are not implemented. Aggregates distinguish actor labels, show denominators and coverage, and exclude visitor IDs. External creator access remains gated on app-scoped authorization and reviewed cohort suppression. No engagement result is claimed by having instrumentation.
Automated builders and browser tests must use a fresh browser context and navigate first with test_agent=1; the shared scripts/test-agent-browser.mjs helper preserves existing query parameters. The enabled bootstrap captures the declaration, removes only that parameter with history.replaceState, and preserves the current history state, other query parameters and hash so app-generated recipient links cannot carry the test tag. The SDK snapshots integer context.test_agent as 0 or 1 when each event is created, so retries remain immutable. The tab-local session marker expires after four hours, survives same-origin navigation and reaches same-origin viewer children, including through bounded page memory when storage is blocked. test_agent=0 clears future tagging only. This declaration has no authorization or identity meaning, and signed QA context retains classification precedence.
Review-to-revision requires durable source-linked records: maker brief and code revision reviewed; reviewer and decision provenance; approved taste used and explanation shown; actual consensual observations; owner triage, decision and resulting release. Nothing here promises the deck's review/match turnaround, growth projections or market outcomes. Riff service/API gaps and acceptance tests are tracked in asks_for_riff.md.
Immersive defaults and direct controls — September 30 revision
Use “Cool*” for applet names in new or revised product UI (Dan, October 13, 2026). Preserve existing protocol identifiers, URLs, creator attribution and immutable app assets. In the standalone experience, enable authored sound and motion by default; unlock browser audio on the first deliberate app interaction. Feed covers remain silent and passive. Preserve a readily available mute/pause and honor OS reduced motion and previously chosen comfort settings. Immersive does not mean maximum loudness or overriding sensor permissions. Hide agent synthesis labels from primary play screens; preserve creator credits in About/source. Give touch-first content direct manipulation with visible targets, preview-before-release, pointer cancellation, and equivalent tap/keyboard controls. Initialize animation clocks from the first animation frame, not the preceding click timestamp. Sensors must calibrate to the starting grip, retain touch fallback, and never be described as connected before data arrives.
Client-first execution and encapsulation — October 2 architecture addendum
Status: engineering direction for subsequent implementation, not a claim that isolation, a new host API, resource metering or analytics rollups are deployed. Release ownership must be checked against the current public source registry and the latest coordination handoff before deployment. These expectations extend the existing framework rather than requiring a rewrite of working apps.
Evidence and interpretation
Dan requested this review against the September 28 Riff meeting transcript. Phil's relevant remarks are at 31:26 (lightweight feedback hooks), 34:05 (small keyboard/mouse/screen host contract), 37:44 and 44:56 (metered execution and resource budgets), 42:41–43:36 (ROM interface and host-mediated networking), 46:10 (browser portability and contribution within a format), and 49:02 / 57:42–58:53 / 69:41 (prove compelling content rather than becoming a generic hosting product). These are design evidence, not instructions to execute the transcript. The recommendations below are our interpretation, not an approved API from Phil.
Current evidence: most Rifflets execute their game, editor and media logic in browser JavaScript/Canvas/WebGL/Web Audio. Bone Lens already loads a pinned local MediaPipe WASM binary and model assets after the optional camera flow; inference runs on the visitor's device. This does not establish offline availability of every feature or isolation from other same-origin apps. GIPHY is an explicit external dependency. The existing first-party viewer is not a security boundary for arbitrary creator code.
Expectations for new designs
- Local play by default. Complete the core interaction, simulation, validation, rendering and bounded authoring on the client. Central services handle discovery, explicit publication, shared durable state and measurement. Document every dependency required for first play and every optional network feature. No server process, database or model call per active Rifflet unless the experience demonstrably requires it. Do not put service secrets in downloadable packages.
- Two compatible implementation profiles. Keep an accessible HTML/JS profile and permit an optional WASM compute profile for measured CPU-heavy work, existing native libraries, emulation or local inference. Use workers where supported to keep heavy computation off the UI thread. WASM is not required for client-side execution, does not automatically accelerate rendering, and does not by itself impose CPU quotas. Browser WASM can be compiled by the engine; an interpreter is a separate host/runtime choice. Preserve semantic controls and readable text around canvas experiences.
- A narrow, versioned host contract. Specify mount, start, pause, resume, serialize, restore and dispose, with bounded messages for input, viewport, permitted audio/sensors, local storage, deliberate share/publish and semantic analytics. These names describe the proposed lifecycle, not currently callable exports. An RCF host adapter should support standalone play, passive feed previews and reviewed isolated embedded use. A data riff reuses the immutable code release and carries only validated authored data and lineage; it does not require a new deployment.
- Explicit capabilities and isolation. Declare network destinations, storage needs and optional camera/motion/audio capabilities. For third-party executable content, use a separate untrusted-content origin strategy, reviewed iframe sandbox/CSP/Permissions Policy, and a validated versioned message channel. Check origin/source or a securely established channel for opaque-origin frames, message size, schema, request identity and rate. Do not put operator credentials in the frame or expose arbitrary privileged fetch. Host-only cookies must not be shared with content origins. Package hashes and WASM memory isolation are not substitutes for this boundary; same-origin JavaScript glue can still access that origin's authority. Storage namespaces alone are not security isolation.
- Bounded execution. A feed shows bounded passive previews; preview browsing never launches a gameplay runtime. A deliberate tap opens one standalone Rifflet in the same tab. Pause offscreen audio, animation and capture; dispose workers, streams and GPU resources when evicted. Declare measured initial/deferred bytes, memory/quality tiers, worker count, asset-cache budget and fallback. Browser scheduling is not hard CPU metering: worker timeouts/termination are an operational safeguard, while strict instruction metering requires a reviewed runtime/interpreter or instrumentation. WASM linear-memory limits do not bound all browser/GPU allocations. Do not globally enable shared-memory headers without checking embeds and external media compatibility.
- Static, immutable delivery. Prefer release/content-addressed assets served through a CDN, bounded browser caching and deduplicated reusable model/media assets. Keep application functions off static delivery routes. Fetch large models only when needed; record asset/license and third-party behavior, including SDK telemetry. Offline support is an explicit tested capability, not implied by client execution. Check cold start, repeat load, denied storage, model failure and interrupted download.
- Bounded central measurement. Use the shared semantic event contract; gameplay must never await analytics. Coalesce frequent observations locally and never upload frame-by-frame camera/audio/sensor input. Preserve meaningful funnel events under declared budgets; session-consistent sampling of detailed diagnostics must retain sampling metadata and make missing coverage visible. Batch with stable event IDs, bounded retry/backoff and queues. Separate private diagnostic records from public feedback. At scale add reviewed asynchronous ingestion where justified, indexed/persisted aggregate reports, cached dashboard results and bounded retention cleanup; do not repeatedly load all raw events per dashboard view. Device context can be referenced once per view/session rather than repeated in every event, with a reviewed schema migration.
Pilot limits and acceptance
The analytics owner confirmed on October 2: memory queue100 events, batch20/32KiB, ordinary delay10s plus bootstrap flush15s, bounded retries, generic diagnostics cap1000/document, current100000-event retained capacity,30-day lazy purge and a10000-row summary cap. A logical event remains a database row even when HTTP requests are batched. There is no sampling, host-message transport, asynchronous queue, persisted rollup or cached summary yet. The password-dashboard release should finish independently; these limits are pilot bounds, not a thousands-of-concurrent-users claim. Follow its release receipt for current production state.
A reference implementation must demonstrate: core play with APIs blocked after assets load; no cross-Rifflet state/privilege access; schema-checked host messages; pause/dispose on feed exit; camera/audio shutdown; bounded package/network/telemetry volume; graceful timeout/capacity behavior; preserved parent/child sharing; and real Android/iOS measurements distinct from desktop tests. Reject undeclared egress and unbounded resource use. Record requests, transferred bytes, meaningful events, stored rows and aggregate-query cost per session before extrapolating capacity. Local computation does not remove media bandwidth, battery, thermal or low-end-device constraints.
Recommended sequence: finish the current analytics/auth release; implement one isolated host/lifecycle reference with a small existing Rifflet; measure and bound analytics volume; then prove the compute profile with a local simulation or composable instrument whose output another visitor can edit. Avoid a blanket WASM rewrite or a new general-purpose OS before this evidence exists.
Technical references: https://webassembly.org/docs/portability/ ; https://webassembly.org/docs/security/ ; https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Concepts ; https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers ; https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe .
Common infrastructure acceptance — October 2, 2026
All published editions must declare an app-specific rifflet.analytics/0.2 contract: meaningful start, up to 12 intermediate milestones, a real final completion or null, and explicit stop/replay boundaries. Each event has one role. Never count an answer reveal, loss, bailout, intermediate level or mere page load as finishing the full experience. The SDK's milestone(key,index?) keeps an attempt open; complete() is final and closes it. Historical completed {} records remain legacy goal evidence. See docs/COMMON_INFRA_COVERAGE.md for the current edition inventory. Keep private choices, option text, camera data and ballots out of analytics; mark private control regions data-analytics-private.
Listen on window for rifflet:pause, rifflet:resume and rifflet:dispose. Suspend animation, physics and sound while hidden or while the shared star menu is open; resume deliberately without time jumps. The shared lifecycle is cooperative control, not an untrusted-code sandbox. Keep execution client-side and server writes explicit, bounded and idempotent.
Hosted scoreboards require explicit public submission consent, bounded names and scores, stable retry IDs, and an unverified-score label until server-verifiable scoring exists. Private group decisions use separate invitation/organizer/member capabilities, expiry and deletion; never publish individual ballots or imply end-to-end encryption. Prompt-seeded curated libraries must identify themselves as curated, not model-generated. Preserve old saves and patch-bump changed editions.
Voice, research and device identity extension
The shared device alias is localStorage-backed on the current origin, with guarded temporary fallback and an explicit reset in the star menu. The opaque local identity ID is never sent. The authorized private analytics directory may observe the generated alias alongside its independent 30-day analytics browser ID, including confirmed changes. It must not use MAC addresses or fingerprints, relink after storage clearing, or treat aliases as unique people. Public scoreboard names remain explicit submissions and are not derived from the private directory.
Song Coach introduces an explicit microphone capability reviewed only for /song-coach and its dedicated viewer; all other paths retain microphone denial. Its audio analysis is a bounded module Worker and raw frames are never uploaded. WebAssembly remains a selective compute option, not a mandatory rewrite. Literal new URL('./worker.js', import.meta.url) references now receive the build’s versioned dependency names.
Auto Quiz uses one allowlisted encyclopedia provider through the existing service, bounded responses, timeout, explicit user initiation and attributed extracts. Question construction and play execute locally. Source snapshots travel in the share data; private queries or confidential study content are not appropriate. Research failure leaves an honestly labeled authored deck available. Both apps reuse opt-in, client-reported scoreboards rather than claiming verified singing or learning ability.
Voice-practice feedback should pair the live measured pitch with the target, an explicit higher/lower cue and a no-signal state. When guide audio plays during microphone analysis, show a prominent headphone recommendation and keep mute reachable; speaker bleed can invalidate a singing estimate. Distinguish transient microphone analysis from recording or saving audio.
Device alias replacement confirmation
The RCF Menu previews the exact current → proposed alias before changing device identity. Confirm applies that proposal; cancel or closing leaves identity unchanged. Scope is all Rifflets on the same origin/browser, not other devices. Previous public posts retain their names and game progress remains. A proposal made stale by another tab must be reviewed again. This implements public feedback 95290d3a-27c3-4e07-a242-35f3356536b0.
Short links and expanded play
New shared state uses the [compact sharing contract](docs/sharing/SHARE_LINKS.md): async app-scoped preparation, fixed expiry, typed bounded payloads, visible invitations and explicit retry. shareRiff/shareShortRiff use the v2 service by default; riffURL remains only for legacy compatibility and an explicitly selected offline export. Preserve old readers. Never silently fall back to the complete encoded link. Browser autoplay requires a gesture; preferred sound-on differs from an active AudioContext. Preserve explicit mute across lifecycle changes. Fullscreen must work as a reversible viewport expansion even without native API support.
Shared rooms and object snapshots — October3
Use the registered shared/collaboration.js transport and server/collaboration service for experiences that genuinely require simultaneous shared state. An app supplies a pure validator, bounded commands with conflict preconditions, and deterministic rendering. One Durable Object owns each room; WebSockets deliver acknowledged state and a server clock. R2 is an optional immutable snapshot store, not the coordination authority. Explicitly distinguish a live room, a saved snapshot and an editable copy. Link access is not verified identity; keep editor/owner capabilities out of URLs and analytics. Declare retention, quotas, conflict behavior, reconnect, lifecycle and an export fallback. Verify actual multiple clients, server restart persistence, capability revocation and snapshot immutability before claiming collaboration. See [the component contract](docs/collaboration/FRAMEWORK_COMPONENT.md) and the release receipt for exact implementation status, including any unactivated R2 dependency. This first-party pilot is not an arbitrary creator-code sandbox, a general CRDT or evidence of human demand.
Analytics audit acceptance
Keep final-finish eligibility tied to each immutable code release, not the app's current contract. Legacy and undeclared measurements remain unavailable. A bounded queue prioritizes journey evidence, and collector diagnostics cannot consume the reserved journey capacity. Partial acknowledgements name each rejected event explicitly; malformed payloads still fail closed. Reports retain selected profiles' history and session classification, enforce the processing cap without partial totals, and export the selected traffic scope. See ANALYTICS.md for precise contracts and remaining scale/privacy limitations.
RCF creator attribution and import review
Every curated Main import packet includes creator.json and import-manifest.json using the proposed review-packet examples in the canonical spec's Creator identity and batch import review packets section. Ask the maintainer to confirm and reuse the creator's existing public creator_<UUID>, or assign a new pseudonymous one. Never accept a pasted ID or matching alias as ownership proof. The optional agreed public alias is only a label; this nonsecret attribution ID is separate from visitor browser/analytics identity and gives no authorization. Credit contributing agents separately from the human/organization owner.
Record importBatchId: batch_<UUID>, each external sourceAppId, source/ref or archive checksum, package path and exact app version. Keep these review fields out of strict content.json; do not rewrite historical manifests or ownership. Preserve immediate parent and original creator on riffs. Approved exact-release mappings may support aggregate stats, search, discovery and attribution, but do not expose raw private analytics. For curated identity/ownership and Main integration, maintainer review remains available. The provisional API now registers pseudonymous creators with private keys and publishes accepted single-app packages automatically. Named/verified creator accounts, bulk batch transport and live creator aggregate dashboards remain pending. Resolve the implemented registration/upload endpoints through AGENT_SUBMISSION.md; a copied creator ID alone grants no authority.
Multiple live editions — approved direction
Promotion must preserve other live editions and exact-version links. Main is the default serving pointer, not the only permitted version. Future personalized serving can choose among authorized editions for each viewer; it is not deployed yet. Before changing publication, routing, retention or attribution, read [Multiple live versions and personalized serving](docs/personalization/MULTI_VERSION_SERVING.md). This direction does not authorize a current promotion or widen private-version access.
One-prompt provisional creator submissions — October 5, 2026
A creator can tell an agent “submit our apps/games/content to riff.marantz.net.” The homepage, /llms.txt and /create/manifest.json lead to [AGENT_SUBMISSION.md](AGENT_SUBMISSION.md), the authoritative no-Git transport workflow. Self-service registration binds a privately persisted random key to a pseudonymous creator ID; labels are unverified and named accounts remain deferred. Every technically accepted package is immediately public provisional content. There is no maintainer review or PR gate for this route, and no automatic Main promotion. Existing Git/review clauses apply to curated platform integration. Preserve immutable submission hashes, exact parent links and the same creator key across updates. Validate the actual sandboxed experience and state unsupported host-service exceptions honestly. Initial registration/storage ceilings bound the pilot; they are not a service-provider billing cap. Reading public guidance grants no authority over unrelated content or spending.
Submission lifecycle: follow the RCF 2.7.0 revision/approval protocol in [the canonical spec](CANONICAL_RIFFLET_SPEC.md). Use the same creator key and slug plus submissionKind: "revision", exact parentSubmissionId, and revisionNotes for an update; use remix for a separate family. Return previewUrl and adminApprovalUrl from the receipt. An authenticated admin approves an exact version for feed/library placement; later uploads stay pending. Approval preserves the sandbox and does not enable hosted analytics or restricted capabilities.
Realtime party rooms — RCF 2.8.0
For a host screen plus phone controllers, declare services: ["realtime-room"] and follow [Realtime Rooms](REALTIME_ROOMS.md). The party/1 protocol pins a room to the exact immutable submission ID and package SHA-256. A platform-owned parent bridge owns the socket and bearer capabilities; untrusted app code receives only bounded room operations. Keep the artifact frame opaque and external networking blocked. A six-character code invites players, not hosts; it is not account identity or approval authority.
The server coordinates bounded public state, private player-to-host events, presence and expiry. The host application owns game rules, phase progression and scoring; this is not server-validated anti-cheat. Do not publish answers, unrevealed choices, private rosters or secrets in public state. Provide disconnect, quota, expiry and offline fallback UI. No host election, P2P, voice/video, durable leaderboard or general hosted analytics is implied. Preserve the RCF 2.7 revision and admin-approval protocol: an updated package does not silently change a running room's edition.
Managed image room dynamics — SDK 1.6.0
Image-enabled provisional apps use premium upload/2 with an operator-reserved creator/slug profile; publication never grants model spend. Follow [managed images](docs/premium/MANAGED_IMAGES.md) and [image-room dynamics](docs/premium/IMAGE_ROOM_DYNAMICS.md) for the exact-revision grant, private projections, durable create recovery, server-owned 60-second turns, private award voting and opt-in reminders. Keep SDK 1.4.0 bytes frozen. Notifications cannot advance gameplay; no hidden prompt or image belongs in a notification payload, analytics or a public link. See engine-generated [snapshot examples](docs/premium/IMAGE_ROOM_EXAMPLES.md).
Premium party/1 admission is specified in REALTIME_ROOMS.md: exact-family entitlement at the gateway, signed bounded creation authority, distinct rolling creation/concurrency counters, unchanged party/1 gameplay. A premium service declaration alone is insufficient, and source availability is not live deployment evidence.
Feed experience pilot — October 13, 2026
Dan approved replacing separate feed cover animations with the real experience for four reviewed apps: Rimowa Classic Cabin, Mercedes G-Class, Neon Snake and Fountain (Water Jugs). This is a finite opt-in release policy, not permission to auto-run arbitrary uploaded code. See [the feed contract](RIFFLET_COVERS.md) and [pilot protocol](docs/feed-mechanics/EXPERIENCE_DEMO_PILOT.md).
The feed is an app-owned, representative demo that hands control to the user in the same isolated instance. Desktop stages cap at 390×780 CSS pixels and shrink proportionally on short windows. Static editorial cover frames belong to /grid and link previews. Preserve original media proportions. Demo state must not consume attempts, persist progress, enable audio/sensors, join rooms or call paid services. The trusted host gates services until deliberate entry. Only the visible card animates; pause, reduced motion and keyboard entry remain supported. Other releases retain their existing inert preview until separately migrated and reviewed.
Preserved editor and common-menu requirements
Prepared-publication lifecycle: when an editor changes or abandons an authored draft, clear its share URL and dispatch rifflet:invalidated so the shared menu removes obsolete publication controls. Prepare and validate the current preview again before publication. This expectation comes from the reproduced Memory Palace review failure where a new preview retained an older prepared instance.
Provide one easy-to-reach, at least 44px, keyboard-accessible in-app hamburger control with recognizable Riff star branding. Its accessible name covers discovery, making a riff and feedback. The menu prominently contains Find your next Rifflet, ✳ Make a riff, Suggest a riff or feature, and Give feedback / report a problem. Preserve existing app-specific editor behavior, public-feedback consent, exact-release context, drafts, receipts and retry semantics. Do not replace a working editor with a copied prompt. Keep instructions, settings and About in the same menu. Opening it must preserve play state and pause/resume through the common lifecycle. Discovery navigates the outer mobile host, not a nested feed inside the phone. Test both ordinary app visits and feed entry.
The current release adds this navigation through a reviewed host adapter on registered app HTML routes; immutable app artifacts and existing feedback handlers are retained. Arbitrary third-party code must still follow the separate isolation and capability review; a menu wrapper does not confer trust.
Analytics before publication and approval
Before publishing a preview or approving any new app/version, follow [Analytics publish and approval checks](docs/analytics/PUBLISH_APPROVAL_CHECKS.md). Review App Stats and Platform Health in the simulator, verify the exact release/submission identity and a marked server receipt (test_agent=1), and check meaningful starts, intermediate milestones and final completion separately. Unknown or local-only telemetry is not verified hosted analytics. Uploaded foreground time and historical family aggregates cannot prove semantic coverage or a new revision's correctness. Record gaps explicitly; preserve existing ownership and approval boundaries.
App startup
Use the shared [app startup contract](docs/APP_STARTUP.md) for app-owned audio and motion initialization. Attempt startup when eligible, report actual blocked/muted/playing state, and retry on a real user gesture. Event-only sounds stay event-driven; startup must not begin scored activities, reveal answers or acquire microphone/paid/room services. Passive feed previews stay silent. Preserve pinned SDKs and publish uploaded adoption as explicit successor revisions.
Live image-room arrival order
The opt-in rifflet.image-room/2 join-order flow lets a creator write an opening
turn before inviting friends. The trusted room service assigns arriving guests
to bounded stable seats and opens their task only when the predecessor image is
ready. Clients render authoritative own-task capabilities; no hidden prompt or
seat credential belongs in the invitation. Legacy rooms retain their pinned
rules. See [the service contract](docs/premium/IMAGE_ROOM_V2.md#join-order-cameraphone-rooms-october-16-2026).
Minimum viable dynamic multiplayer
Campfire and Cameraphone support opt-in dynamic-v1 rooms: start automatically
with two people (host may choose 2–6), admit late friends up to six, and schedule
two turns each with twelve maximum. Admission closes after ten minutes of play
or when the final scheduled turn starts. The persisted future plan extends
without changing active tasks; private inputs/missions remain per-seat. See the
[dynamic room contract](docs/premium/IMAGE_ROOM_V2.md#dynamic-rooms-for-campfire-and-cameraphone-october-16-2026).