# `Stage.set`

> Contract 2.0.0 · package sha256 `a857eca95b35921109faf997094bb4192f12527d9d0fcd4be7e97f06425bad6e` · generated from `configurator-runtime.d.ts` by `services/onsite-scripter/scripts/build-contract-docs.mjs`; edit the source, not this file.

Method of [`Stage`](Stage.md) · stable · since 2.0.0 · called as `session.stage.set`

```ts
set(settings: StageSettings, options: C & StageWriteOptions): Promise<Report>;
```

Replaces the owner's stage layer, which merges over the document's settings. The layers stack
over the document's, each collection's in the order
of its first write (as rules, spec section 6.10, R2; [`state().look.stageOrder`](LookState.stageOrder.md)); a later write
replaces a layer in place without moving it. Each merges over the ones below as a layer merges over the document's, so
disjoint keys all apply and, on a key two layers set, the later-stacked one wins. Where a layer
and the value merged below it both hold an object for `environment`, `ground`, `ground.shadow`,
`ambientOcclusion`, `bloom` or `grade`, they merge field by field, and a URL-less `environment`
object also retunes a built-in below it (over 'none' it turns nothing on). Every other value
replaces whole: `background` in any form, its texture included, `ground.shadow.on`, a
`toneMapping` curve, and a string or boolean over an object or the reverse: an object over a
merged `true` or `false` (`ambientOcclusion`, `bloom`) turns the effect on, and the fields it
omits take the document's. An `environment` with a `url` over a lower object keeps the
`intensity`, `rotationDeg` and `blur` it omits from that object. A field no layer
sets takes the document's; for `background`, the committed scene model's non-null
`backgroundColor` first, which lies over the document's and under every layer
([`BackgroundValue`](BackgroundValue.md)). Disposing an
owner removes only its layer. Look-only; replacing and in the write queue
(target: that owner's layer). An environment or panorama it names loads hidden and swaps in one
frame when its image differs from the one drawn in that slot. One equal to the drawn image (the
same URL as `fetch()` resolves it, or the same [`ImageRef`](ImageRef.md) sha256), named again by this member,
[`CollectionSpec.stage`](CollectionSpec.stage.md) or [`apply()`](Writer.apply.md), is kept: no request, decode, prefilter, upload or
readiness wait. The drawn image is one the slot draws when the write is called or reaches its
commit point, either side of a running fade, and no commit frees an image a pending write names
before that write commits or ends. A changed `rotationDeg` or `intensity` then applies in the
commit's frame, a
changed `blur` filters the kept image again without a request or a decode, and with `fadeMs`
those fields tween over the one image, never a crossfade of two copies.
Timing: resolves at the commit point, or when `fadeMs` ends or a newer write to the layer
takes it over. Through a `tx`: 'staged' once the environment or panorama it names has loaded
(at once when it names none), and `fadeMs` starts when the commit is shown (spec section 6.3).
Errors: rejects HoloInputError on invalid settings.
An environment or panorama that fails is a
problem ('asset-failed', `path` `/look/collections/{name}/stage`, `asset` 'environment' or
'texture', [`Problem.path`](Problem.path.md)): the rest of the settings commit, and the environment or panorama
drawn before stays, as a failed texture keeps its slot's look (spec section 6.4).

## Options

Through [`Session`](Session.md):

| Option | Type | Default | What it does |
| --- | --- | --- | --- |
| `actor` | `Actor` | the `expectGroup`'s actor when one is given, else 'app' | Who made the write. |
| `dryRun` | `boolean` | false | Runs and reports, then rolls back by design ('dry-run'). |
| `expectGroup` | `HistoryGroup` | undefined | A guard, checked at the call: this write belongs to the undo group you are running. |
| `expectRevision` | `number` | undefined (no check) | If-match on [`session.revision`](Session.revision.md). |
| `fadeMs` | `number` | 0 | Crossfade to the new settings. |
| `origin` | `string` | null | Your tag, echoed unchanged in [`Report.origin`](ReportFields.origin.md) and `cause.origin`. |
| `owner` | `Collection` | — | Required: the collection whose stage layer this call writes; its `set` replaces the same layer ([`CollectionSpec.stage`](CollectionSpec.stage.md)). |
| `signal` | `AbortSignal` | undefined | Cancels this call; the member's JSDoc says what an abort does. |
| `supersede` | `boolean` | false (the write is queued behind the transaction and applies after it closes) | While a transaction is open: roll it back (it resolves 'superseded'); the writes queued behind it apply in call order, then this one, which supersedes an… |
| `undo` | `'rebase' \| (string & {})` | a recorded-state change gets one step labelled 'Change'; a look-only write gets none; the session's first model (cause 'load') gets none, whatever the label: it is the floor of history | An undo label makes this write one undo step. |

Through [`Tx`](Tx.md):

| Option | Type | Default | What it does |
| --- | --- | --- | --- |
| `fadeMs` | `number` | 0 | Crossfade to the new settings. |
| `owner` | `Collection` | — | Required: the collection whose stage layer this call writes; its `set` replaces the same layer ([`CollectionSpec.stage`](CollectionSpec.stage.md)). |
| `signal` | `AbortSignal` | undefined | Cancels this call; the member's JSDoc says what an abort does. |

Refused here (typed `never`, so passing one fails to compile): `actor`, `checkpoint`, `dryRun`, `expectGroup`, `expectRevision`, `origin`, `supersede`, `undo`.

## Abort (`signal`)

This call is a write (`SignalOption.signal`, [the kinds of call](../read-this-first.md#conventions)).

> A write: before the commit point it rolls back and rejects AbortError; after it, no effect, except that a running camera move stops where the last frame drew it (`CameraMoveOptions`).
>
> Through a `tx` the commit point is the transaction's: aborting a write still loading rejects AbortError and stages nothing (catch it: unobserved, it rolls the transaction back, spec section 6.1, O6); aborting one already staged unstages it, its paths keeping the latest other write to them as after a failed savepoint (O7), and its Promise stays resolved 'staged'.

## Example

Imports: values (`has`, `validate`, the `Holo*Error` classes, the pure helpers) from `@holostep-configurators/runtime-client`, types from `@holostep-configurators/runtime-client/contract`, `/math` and `/testing` names from those entries; `boot` from the runtime module the root's `loadRuntimeAtFloor` resolves to. A type your page defines is your app's: declare it there, never import it from the package.

Compiled under the contract's strict settings (`examples/declaration/09-Stage.set.ts`):

```ts
import type { Session } from '@holostep-configurators/runtime-client/contract';
declare const session: Session;
declare const signal: AbortSignal;
// A night mode as its own layer: disposing it restores the stage underneath.
const night = session.collection('night-mode', { role: 'helper' });
await session.stage.set(
  { exposureEv: -1.2, background: '#101820', lights: { intensity: 0.4 } },
  { owner: night },
);
export function dayMode(): void {
  night.dispose();
}
```

## Generic-API test (spec 3.1)

| Rule | Result |
| --- | --- |
| 1. Neutral name | pass: `set` names no product |
| 2. A precedent | pass: [Babylon.js ImageProcessingConfiguration.exposure](https://github.com/BabylonJS/Babylon.js/blob/master/packages/dev/core/src/Materials/imageProcessingConfiguration.ts) (row `E6`); [Unity RenderSettings.ambientIntensity](https://docs.unity3d.com/ScriptReference/RenderSettings-ambientIntensity.html) (row `E6`); [CSS linear-gradient()](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient) (row `K23`); [Unity RenderSettings](https://docs.unity3d.com/ScriptReference/RenderSettings.html) (row `K28`) |
| 3. Two apps, or labs | pass: 19 apps (ledger: app-378d190f1b, app-4f16d2f6da, app-510d750508, app-59c5b5751e, app-b362a81c85, app-ceb4eccc72, app-fc07850558, app-fc306ec3dc; fleet cross-check: app-04c2774145, app-0c773a4ee3, app-378d190f1b, app-4762caacdc, app-4f16d2f6da, app-510d750508, app-59c5b5751e, app-b362a81c85 and 11 more) |
| 4. The cheaper fix first | decided per need in Appendix B: rows `E6`, `K23`, `K28`, `K30` at tier stable (a member only where no rule, data, asset or app code serves the need) |
