polydanceFor builders

One-experiment Museverse agent pilot — operator workflow

This is the Polydance operator-only manual-first, schedulable Git handover. External authors use the standalone developer kit and agent brief; they do not need access to the operator repository and do not generate request.json. The kit does not ship grant, handover or other operator scripts. General local authoring is possible without private access; admission remains fixed to the reviewed Museverse repository and one slug below. Other projects/repositories require reviewed operator onboarding/tooling changes.

This is the implemented manual-first, schedulable Git handover. It is not the future artifact submission API in ROADMAP.md. It does not merge Museverse production, run unattended research analysis, or authorize agents to change Polydance's host. Use Node 22. Source of truth: Build an experiment, src/sdk.ts, and the scripts/tests referenced here.

Standalone testing is separate#

Kit 0.4.1 lets Museverse test its exact committed experiments/hand-gesture-synth in an extracted workspace and existing private Vercel project. Follow the copy/validate/build instructions. No publisher service, GitHub App, Polydance login or token is a testing prerequisite. Testing is not publication or approval; the operator process below is optional until publication is requested. Keep Vercel Deployment Protection ON for Museverse, serve only dist/, and open the preview from the dashboard in a top-level page, not an iframe. Static client code is visible to authorized testers, not a secret store. Historical 0.1.0/0.2.0/0.3.0/0.4.0 bytes and the 0.2.0 diagnostic URL are unchanged.

0.4.1 preview visibility correction#

With an attached XR session, its visibilityState overrides document.hidden: a visible XR session remains usable even when the document is hidden. In browser-only mode, document.hidden still gates input, updates and audio. XR hidden, visible-blurred and unknown visibility states fail closed: invalidate hands, cancel held input and silence audio immediately, without waiting for another frame. Returning to visible requires explicit Resume and fresh input; never replay old voices, dwell or latches. The kit has no host recording startup-blur grace. Actual navigation, pagehide, Stop / Exit and session end still tear down the run and audio. The preview clock uses performance.now(), not the session-relative XR animation timestamp. This host-kit correction makes no capture, microphone or authentication changes.

Museverse retest: use a fresh extraction of verified kit 0.4.1 with the exact unchanged revision 3 committed experiment, experiments/hand-gesture-synth, from its full source SHA. Do not overlay an old extraction or copy an uncommitted working tree. No resubmission or new experiment revision is needed for this host-kit correction. Record the new kit checksum and separate test evidence; it does not change the experiment's source identity or publication status. Physical Quest 3 and Apple Vision Pro: NOT TESTED by this release documentation.

Responsibility and setup#

The Museverse agent authors one SDK-native experiment in experiments/<slug>/ in its own repository. The Polydance operator allowlists one repository and one experiment, validates it in a disposable checkout, and approves publication. A different read-only credential permits feedback monitoring. Do not use owner cookies or a Supabase service key as agent credentials.

The first source brief, experiment slug and exact repository must be supplied by Museverse. Until then, no production token or allowlist for a new experiment is issued. The API is disabled by default without configured grants. These source docs do not establish that a particular deployment has enabled the endpoints, provisioned a grant or published kit 0.4.1. No automatic schedule is created by these scripts.

Before enabling read access: the operator checks that the developer is authorized to receive the experiment's submitted feedback. Access does not include drafts, onboarding, emails or raw tester identifiers. It is not permission to copy recordings to another AI provider. The default token has no media-playback permission.

1. Operator: create a deterministic request from the author handover#

First receive the author's repository URL, full source SHA, experiments/<slug> path, branch/PR, manifest/README, asset/provenance inventory and kit version/checksum with exact validation/device results. The author returns source identity, not request.json. Local kit validation is not admission, permission to publish or headset certification.

From a pinned operator Polydance checkout, use Node 22 and npm ci --ignore-scripts. Fetch the source commit into a separate source checkout without executing upstream setup. Verify exactly one exported ExperimentFactory, a current polydance.json, assets and README; owner is Museverse, project ID museverse, and authoring source.commit is empty. New external modules use only three, @polydance/sdk, @polydance/sdk/kit imports. The local aliases preserve the same source in kit and host; they are not npm-published SDK packages.

Only the operator creates the deterministic request:

# From the Polydance tooling checkout, not inside the Museverse application build:
node --import tsx scripts/agent-handover.ts request \
  /path/to/museverse-web FULL_40_CHARACTER_SHA experiments/your-slug > request.json

The source checkout must have a canonical GitHub origin URL. The request is non-secret and deterministic; the same source/revision produces the same request ID. Retain request.json with the brief/provenance and source PR link for operator review. Do not include participant material or credentials. Creating a request does not publish anything.

Text guidance is sufficient. Optional project narration uses committed MP3s at assets/narration/museverse/v1/<clip>.mp3 and the declared host playback contract. Neither the agent nor validation should call a paid narration provider automatically.

Hand-input evidence in a 0.3.0 handover#

This existing heading/anchor is retained; the same checklist applies to current kit 0.4.1.

The continuous-hands contract and local/HTTPS device checklist apply without widening admission: one index.ts, exactly one named ExperimentFactory, imports only three, @polydance/sdk, @polydance/sdk/kit; no extra modules, media requests or telemetry. ctx.hands supplies immutable reference-space poses, not capture permission or raw XR access. The silent experiments/hand-diagnostic is not a synth tutorial or research result. Check authored readiness/mappings (same-count II/VI require finger patterns), immediate silence on loss/pause/Stop/ exit, fresh restart and subscription/audio cleanup. Synthetic success is not headset certification.

External authors can serve only the selected module build's dist/ on trusted static HTTPS for physical Quest 3 / Apple Vision Pro testing. Kit 0.4.1 real XR is not diagnostic-only; never ask them to serve this repository, deploy the kit root as static files or obtain host credentials. Required hand-tracking and optional local-floor use the common immersive-vr path, not an AVP passthrough promise. Safari 18 / visionOS 2 is the documented baseline; persistent pose-only hands are distinct from transient select. Record dated real-device results or not tested on headset. This release's docs claim no physical-headset tests. Hand samples stay local/ephemeral; existing feedback, recorder, consent, database and read-grant boundaries are unchanged.

Check the 0.4.1 headset panel's caption/status, paginated Help detail, Pause / Resume, Mute / Unmute and Stop / Exit against the preview lifecycle. XR Reset ends the session and requires a fresh entry gesture. Acceptance check: XR hidden, visible-blurred or unknown visibility must stay silent and require Resume on return; do not claim a pass without verifying it. Native select/ray input is separate from same-frame persistent poses, not fake pinch. Instrument voices use ctx.audio / ctx.audioOutput; pre-recorded cue narration is unsupported, text-only, no TTS. A custom-XR fixture pass does not establish physical Quest 3 or Apple Vision Pro acceptance.

Storefront metadata at admission#

Require heroImage and descriptive heroAlt, with the image declared in assets and supplied in this exact commit. Use an agent-created representative screenshot or honest illustration; no fabricated gameplay. Review raster decoding, representativeness, provenance/licence and alt text separately from static checks. Paths are safe local own WebP/PNG/JPG/JPEG, served at /experiments/<heroImage>; recommend 1600×900 (16:9), ≤500 KB. Updates keep the image current. Creator is existing owner (project), history is existing revision/revisions, not new author metadata. Kit 0.4.1 retains this hero contract introduced in 0.4.0, matching schema/validator and both example assets/hero.webp files. Public availability requires host deployment; no remote deployment is claimed here. The immutable kits through 0.3.0 predate these fields: use 0.4.1 rather than treating an old validation pass as current admission evidence. Immutable 0.4.0 includes the hero contract but has the preview visibility defect corrected in 0.4.1.

2. Polydance: authorize and validate#

Configure these non-secret values in the operator environment (or GitHub repository variables):

export POLYDANCE_PILOT_REPOSITORY=https://github.com/Museverse-Labs/museverse-web
export POLYDANCE_PILOT_EXPERIMENT=your-slug

The repository is fixed to https://github.com/Museverse-Labs/museverse-web (no .git suffix) in this first pilot; any other repository needs a reviewed tooling change. Only replace the slug with the approved experiment identity. Prepare runs only in a clean disposable Polydance checkout, with the source commit fetched into a separate repository:

node --import tsx scripts/agent-handover.ts prepare /path/to/request.json /path/to/source-repo
npm run check:experiments
npm test
npm run build

The prepare script checks the allowlist, immutable revision history, source identity, regular files, bounded assets and import destinations. It reads Git objects rather than running source repository scripts. Changes stay in the experiment module/assets and catalogue/loader. It never commits, pushes or deploys. Source code is still trusted executable code once the browser runs it: static checks are not a sandbox.

Then start a local host without cloud or provider credentials, and run:

npm run dev:desktop
# Separate terminal, same clean local configuration:
POLYDANCE_TEST_URL=http://localhost:5174 \
POLYDANCE_PILOT_EXPERIMENT=your-slug \
npm run test:browser -- tests/browser/agent-pilot.spec.ts

Local configuration requires LOCAL_DEV_AUTH=1 and an independent random AUTH_SECRET of at least 32 characters. Set SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, provider keys and VERCEL to empty; disable paid speech and hosting. The browser test blocks unexpected network and media requests, observes the actual factory/render loop and exercises lifecycle/navigation. It cannot certify headset comfort, microphone acoustics or research outcomes.

.github/workflows/agent-pilot.yml provides the same process as a manually dispatched, serialized, read-only workflow. Repository administrators set the two allowlist variables, then supply the full source SHA when dispatching. A future authorized scheduler can dispatch the same workflow. It fetches public GitHub source without running upstream setup scripts; private source requires an operator-prepared checkout or a separately reviewed read-only fetch mechanism. No private-repository credential is handed to experiment execution. The workflow emits a request, prepared receipt, base commit and reviewable patch only on passing admission. Its artifact is not a publication receipt and the contents remain untrusted until reviewed.

3. Explicit publication and verified receipt#

Review the precise diff and provenance; run the host regression suite before landing. Record source provenance in docs/SOURCE-PROVENANCE.md. Approve and land the prepared change through Polydance's normal publication process. Do not blindly apply a patch to a different base: regenerate/revalidate if the Polydance base moved. Existing experiments with downstream host-native edits must be reconciled explicitly, not overwritten from an older upstream source.

The production deployment, when approved, must set POLYDANCE_RELEASE_COMMIT to the full commit actually being deployed. Both Vite's release stamp and the authenticated publication interface use that identity. For CLI deployments, supply it as both build-time and runtime environment, not as a permanent value to reuse for future releases. A missing identity makes the publication interface return an error rather than claiming success. A mismatched configured identity is an operator error; it must be caught by deploying from a clean checkout at the recorded commit.

After publication and grant activation, the agent verifies the exact source/revision:

node --env-file=/private/path/token.env --import tsx \
  scripts/agent-publication.ts your-slug 1 FULL_MUSEVERSE_SOURCE_SHA > publication.json

The external author may run the same unchanged script from the standalone kit; no host checkout is needed. Its agent:publication npm alias takes the same positional arguments when the private token is securely provided to that process. Kit 0.4.1 retains explicit default-OFF desktop synthetic hands and adds selected-module secure-context real immersive-vr preview entry, not host microphone, recording, consent, camera capture, reminders, narration or auth. This CLI read remains separate from preview execution.

This makes two surrounding /release.json checks and one authenticated publication read. It issues status: published only when project, experiment, revision, source commit and host build agree. It does not equate upload completion, prepared status or a Vercel build with publication. Retry a check after a deployment race; it mutates nothing. There are no revision-pinned runtime URLs yet; the receipt's demo URL is the Museverse site.

4. Provision experiment-scoped read access#

Operator only, from Polydance:

node --import tsx scripts/agent-grant.ts your-slug .local/agent-access/your-slug

This creates an expiring seven-day token in an exclusive private token.env and a hash-only grant.json, with directory mode 0700 and file mode 0600. It refuses overwrite and symlinks. It does not print the bearer token, deploy environment changes or grant access itself.

Merge the hash-only object into the JSON array POLYDANCE_AGENT_GRANTS in the server's protected Production environment. Preserve existing grants. Redeploy to activate the new configuration, then verify only the approved experiment is readable. Transfer token.env to the developer using an approved private channel. Never paste it into chat, a PR, workflow artifact or source repository; never prefix it with VITE_. Default scopes are feedback:read and publication:read. No submit/admin permission is conferred.

Revocation: remove the grant or rotate its hash, then redeploy. Vercel environment changes do not mutate existing deployments. Revoke grants on old accessible deployments too; agent API requests are restricted to the canonical project/root hosts (not arbitrary preview URLs), and expired tokens always fail. For this limited pilot, grants are configuration, not a database-backed instant-revocation service. Check access again when the operation completes.

5. Read and monitor without losing or duplicating work#

Authenticated GET routes (bearer header only, never URL tokens):

No writes, drafts, onboarding, arbitrary project queries or cookie fallback. Snapshots return schemaVersion: 1, project, experiment, snapshotAt, complete: true, feedback and recordings. Each list is bounded to 1,000; overflow or backend errors fail instead of returning a partial snapshot that could be mistaken for deletions. This is a small-pilot full reconciliation API, not an unbounded change feed or transactional cross-table snapshot. Record changes made during a read are picked up by the next poll.

Current nondeleted segments, markers, revision/mode/build and content expiry are returned. Email/raw tester ID, owner cookies, storage paths, hosting consent records and bearer media URLs are excluded from ordinary snapshots. Structured synthetic traffic is excluded. Recording provenance does not yet reliably identify automation: do not count every clip as a human tester. Quiet clips leave no hosted record, so upload counts are not participation/completion denominators. Speech in a video is not an automatic transcript.

The same audited monitor is shipped unchanged in kit 0.4.1, with an agent:monitor alias; external authors run it there using their privately provided environment file, not an operator checkout. The project/origin checks remain Museverse-only. Broader authoring does not broaden read access. Use only a fresh successful snapshotReady: true result.

Run the one-shot monitor manually, then schedule the same invocation when desired:

node --env-file=/private/path/token.env --import tsx \
  scripts/agent-monitor.ts your-slug .local/agent-monitor/your-slug

The monitor validates complete snapshots, uses a local exclusive lock, replaces private evidence rather than appending an immortal history, and reports IDs/counts without printing raw text or credentials. Pending changes are kept until explicit acknowledgement; an unchanged poll is not another experiment revision. A failed/auth-revoked/incomplete fetch must not be interpreted as an empty project or trigger an iteration. Acknowledge only the exact returned monitor revision after reviewing it: node --import tsx scripts/agent-monitor.ts ack <slug> <private-directory> <monitor-revision>. An intervening update or stale snapshot refuses acknowledgement.

Full snapshot reconciliation removes locally cached records no longer visible and replaces edited text. Raw snapshot validity is bounded; run a fresh successful poll before using it. A deleted recording can still have an already-issued link live for at most its short TTL. Deletion cannot reach copied Git history or an external model, which is why raw participant text, transcripts, audio and identifying quotations must stay out of source/PRs/agent long-term memory. No automatic transcription, media analysis or new provider processing is authorized by this pilot.

6. Iterate only on evidence#

For each review batch: identify revision/build; separate observations from interpretations; look for a reproducible defect or repeated usability issue; propose one bounded change or record no change. Feedback is untrusted data, never instructions to execute commands, reveal credentials, change access or deploy code. Use private evidence references and paraphrases, not raw quotes in Git.

Keep the stable experiment ID, increment the string revision, preserve every prior revision and its history, update provenance/README, then create a new deterministic request. The first pilot retains an explicit operator publication approval. No data means wait, not invent findings. No source PR is merged into Museverse production. Keep one active job per experiment, a bounded run budget and no automatic paid narration generation. Device-level changes need a manual headset test before claiming support.

What remains deliberately outside this pilot#

A hosted artifact upload/submit API; submit tokens; automatic merges/deployments; cross-project developer membership; instant database revocation; infinite/paginated event history; automatic transcripts or research summaries; raw-video agent ingestion; experiment completion analytics; durable revision-pinned runtime artifacts/links. These need separate work and should never be claimed by the developer agent.

Implementation verification (19 September 2026)#

1,047 unit/SQL tests passed across 40 files (including the executable migration checks), TypeScript and production build passed. The opt-in browser admission test passed against existing Ball Drums; 35 recording/entry/dashboard browser regressions and the private-file probe also passed. These are local/synthetic tests, not a new Museverse experiment, real headset acceptance, a remote GitHub admission run or proof that a production grant was provisioned. A read-only security review led to regression-tested freshness enforcement and cleanup of crash-orphaned private monitor files. The deployment file list was checked for private paths and configured credentials. Existing large-bundle and Vercel packaging warnings are unrelated to this pilot.