scenri 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +12 -12
- package/dist/serve.js +39 -4
- package/package.json +1 -1
- package/studio-dist/assets/index-DBz4hsVB.js +102 -0
- package/studio-dist/index.html +1 -1
- package/studio-dist/assets/index-BGiMfD5T.js +0 -102
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.4](https://github.com/tonygorb/Scenri/compare/v0.3.3...v0.3.4) (2026-08-20)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* presenter references are identity, not wardrobe ([dc372fd](https://github.com/tonygorb/Scenri/commit/dc372fd40d7e15d7d8dc72b5ec8f41993e078ae9))
|
|
9
|
+
* presenter references are identity, not wardrobe ([c8bca43](https://github.com/tonygorb/Scenri/commit/c8bca431730a2d4c41d2783fb6eba2c564af5141))
|
|
10
|
+
* stop custom presenter and scene pages freezing the whole app ([fcf88dd](https://github.com/tonygorb/Scenri/commit/fcf88ddbcd57d01354c833cf9f8456fa1b0b0434))
|
|
11
|
+
* stop custom presenter and scene pages freezing the whole app ([8595078](https://github.com/tonygorb/Scenri/commit/859507893892cb23a7ff2f132f273db4dbd0a0f9))
|
|
12
|
+
|
|
13
|
+
## [0.3.3](https://github.com/tonygorb/Scenri/compare/v0.3.2...v0.3.3) (2026-08-20)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* absolute README links so they survive the npm package page ([c8b2cd0](https://github.com/tonygorb/Scenri/commit/c8b2cd04e6f4a2e6be9e7470b970c2d5033d60d4))
|
|
19
|
+
* absolute README links so they survive the npm package page ([16219cf](https://github.com/tonygorb/Scenri/commit/16219cf848279f58ab2d1e0db46e5f3efffeb388))
|
|
20
|
+
|
|
3
21
|
## [0.3.2](https://github.com/tonygorb/scenri/compare/v0.3.1...v0.3.2) (2026-08-20)
|
|
4
22
|
|
|
5
23
|
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Define a client's brand once. Then generate, branch, and art-direct on-brand ima
|
|
|
11
11
|
|
|
12
12
|
[](https://github.com/tonygorb/scenri/actions/workflows/ci.yml)
|
|
13
13
|
[](https://www.npmjs.com/package/scenri)
|
|
14
|
-
[](LICENSE)
|
|
14
|
+
[](https://github.com/tonygorb/scenri/blob/main/LICENSE)
|
|
15
15
|
|
|
16
16
|
**Get started:** one command, no account.
|
|
17
17
|
|
|
@@ -19,7 +19,7 @@ Define a client's brand once. Then generate, branch, and art-direct on-brand ima
|
|
|
19
19
|
npx scenri
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
<sub>Needs [Node.js](https://nodejs.org) 22 or newer. New to any of this? The [install guide](docs/INSTALL.md) walks through every step.</sub>
|
|
22
|
+
<sub>Needs [Node.js](https://nodejs.org) 22 or newer. New to any of this? The [install guide](https://github.com/tonygorb/scenri/blob/main/docs/INSTALL.md) walks through every step.</sub>
|
|
23
23
|
|
|
24
24
|
<img src="https://raw.githubusercontent.com/tonygorb/scenri/main/docs/media/demo.gif" alt="The Scenri composer: a dollar sign opens a product picker and Selvedge Trucker is chosen, an at sign picks the presenter Maren, a slash picks the Editorial Walk scene, a line of written direction is typed after the three chips, the shot renders as a card in the wall, and it opens to show the picture beside the brief that made it" width="820">
|
|
25
25
|
|
|
@@ -57,7 +57,7 @@ The brand kit sits one gesture away in Settings and is the part that keeps outpu
|
|
|
57
57
|
|
|
58
58
|
## Run it
|
|
59
59
|
|
|
60
|
-
Scenri runs on [Node.js](https://nodejs.org), version 22 or newer. If you are not sure you have it, or terminals are not part of your day, the **[install guide](docs/INSTALL.md)** covers every step for macOS, Windows and Linux. With Node in place:
|
|
60
|
+
Scenri runs on [Node.js](https://nodejs.org), version 22 or newer. If you are not sure you have it, or terminals are not part of your day, the **[install guide](https://github.com/tonygorb/scenri/blob/main/docs/INSTALL.md)** covers every step for macOS, Windows and Linux. With Node in place:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
npx scenri
|
|
@@ -67,7 +67,7 @@ That is the whole install. npm asks once whether to proceed, downloads the curre
|
|
|
67
67
|
|
|
68
68
|
Generation runs on **Codex CLI**, an official helper from OpenAI that draws on your own ChatGPT plan. No API key to paste, and Scenri never charges you. Each image draws on your plan's Codex usage. You do not have to set it up by hand: if it is missing, Scenri offers to install it and to sign you in, both from the app. No ChatGPT plan? Add your own key from an image provider in Settings instead, see [Engines](#engines).
|
|
69
69
|
|
|
70
|
-
Two dependencies (`better-sqlite3` and `sharp`) ship native binaries, so on recent npm you may be asked to approve their install scripts once. Something not starting? See [troubleshooting](docs/INSTALL.md#troubleshooting).
|
|
70
|
+
Two dependencies (`better-sqlite3` and `sharp`) ship native binaries, so on recent npm you may be asked to approve their install scripts once. Something not starting? See [troubleshooting](https://github.com/tonygorb/scenri/blob/main/docs/INSTALL.md#troubleshooting).
|
|
71
71
|
|
|
72
72
|
<details>
|
|
73
73
|
<summary>Run from source</summary>
|
|
@@ -95,7 +95,7 @@ pnpm dev # starts the server on 127.0.0.1:4747
|
|
|
95
95
|
- **Iteration is the product.** A version tree, not a prompt box. Branch, compare, keep the winners.
|
|
96
96
|
- **Your brands are files, not hostages.** `.brand` is an open, documented format under a permissive license. Email one to a client. Any tool can adopt it.
|
|
97
97
|
- **Your AI, your cost.** Bring your own Codex CLI session or an API key. Experiments cost raw API price, or nothing at all on a local session. No credits that burn on a miss.
|
|
98
|
-
- **Local first, and it means it.** No account, no telemetry, no upload. The server binds to your machine only. Scenri makes exactly two requests on its own behalf: a daily version-number check against npm so updates can announce themselves, and a one-time download of the library imagery archive, cached locally forever after. Nothing about you or your work is ever sent, and both turn off: in Settings or `SCENRI_NO_UPDATE_CHECK=1` for the first, `SCENRI_NO_CONTENT_FETCH=1` for the second ([how updates work](docs/updates.md)).
|
|
98
|
+
- **Local first, and it means it.** No account, no telemetry, no upload. The server binds to your machine only. Scenri makes exactly two requests on its own behalf: a daily version-number check against npm so updates can announce themselves, and a one-time download of the library imagery archive, cached locally forever after. Nothing about you or your work is ever sent, and both turn off: in Settings or `SCENRI_NO_UPDATE_CHECK=1` for the first, `SCENRI_NO_CONTENT_FETCH=1` for the second ([how updates work](https://github.com/tonygorb/scenri/blob/main/docs/updates.md)).
|
|
99
99
|
|
|
100
100
|
## Engines
|
|
101
101
|
|
|
@@ -148,23 +148,23 @@ One package publishes to npm: **`scenri`**, the CLI, which bundles everything el
|
|
|
148
148
|
|
|
149
149
|
## Contributing
|
|
150
150
|
|
|
151
|
-
Start with [CONTRIBUTING.md](CONTRIBUTING.md). Engine adapters are the friendliest surface: one file, one interface, well covered by tests.
|
|
151
|
+
Start with [CONTRIBUTING.md](https://github.com/tonygorb/scenri/blob/main/CONTRIBUTING.md). Engine adapters are the friendliest surface: one file, one interface, well covered by tests.
|
|
152
152
|
|
|
153
|
-
Accessibility is tracked in [docs/A11Y-BACKLOG.md](docs/A11Y-BACKLOG.md). Every Biome a11y rule runs at `error`, so the backlog is currently empty and a new defect fails CI rather than joining a list.
|
|
153
|
+
Accessibility is tracked in [docs/A11Y-BACKLOG.md](https://github.com/tonygorb/scenri/blob/main/docs/A11Y-BACKLOG.md). Every Biome a11y rule runs at `error`, so the backlog is currently empty and a new defect fails CI rather than joining a list.
|
|
154
154
|
|
|
155
|
-
Found a security problem? Please report it privately. See [SECURITY.md](SECURITY.md).
|
|
155
|
+
Found a security problem? Please report it privately. See [SECURITY.md](https://github.com/tonygorb/scenri/blob/main/SECURITY.md).
|
|
156
156
|
|
|
157
157
|
## Status
|
|
158
158
|
|
|
159
|
-
Early. The version is `0.x` and interfaces can still move. Everything documented above works today. [ROADMAP.md](ROADMAP.md) says what is next.
|
|
159
|
+
Early. The version is `0.x` and interfaces can still move. Everything documented above works today. [ROADMAP.md](https://github.com/tonygorb/scenri/blob/main/ROADMAP.md) says what is next.
|
|
160
160
|
|
|
161
161
|
## License
|
|
162
162
|
|
|
163
|
-
The application is [AGPL-3.0-only](LICENSE). The `.brand` format, its schema, and its validator live in [packages/brand-spec](https://github.com/tonygorb/scenri/tree/main/packages/brand-spec) under Apache-2.0, so any tool may implement or reuse them without taking on copyleft; the npm package carries that license text as `LICENSE-APACHE-2.0-brand-spec`. Contributions require a [CLA](CLA.md).
|
|
163
|
+
The application is [AGPL-3.0-only](https://github.com/tonygorb/scenri/blob/main/LICENSE). The `.brand` format, its schema, and its validator live in [packages/brand-spec](https://github.com/tonygorb/scenri/tree/main/packages/brand-spec) under Apache-2.0, so any tool may implement or reuse them without taking on copyleft; the npm package carries that license text as `LICENSE-APACHE-2.0-brand-spec`. Contributions require a [CLA](https://github.com/tonygorb/scenri/blob/main/CLA.md).
|
|
164
164
|
|
|
165
|
-
The bundled imagery and curated content are licensed separately under [ASSETS-LICENSE.md](docs/ASSETS-LICENSE.md): free to use within Scenri, commercial work included; no redistribution or rebundling. The npm package's `license` field describes the code; the starter imagery inside it stays under those asset terms.
|
|
165
|
+
The bundled imagery and curated content are licensed separately under [ASSETS-LICENSE.md](https://github.com/tonygorb/scenri/blob/main/docs/ASSETS-LICENSE.md): free to use within Scenri, commercial work included; no redistribution or rebundling. The npm package's `license` field describes the code; the starter imagery inside it stays under those asset terms.
|
|
166
166
|
|
|
167
|
-
The name and the mark are not part of the code license: [TRADEMARKS.md](TRADEMARKS.md) says what a fork may and may not call itself. What the app does and does not send anywhere is written down in [PRIVACY.md](PRIVACY.md).
|
|
167
|
+
The name and the mark are not part of the code license: [TRADEMARKS.md](https://github.com/tonygorb/scenri/blob/main/TRADEMARKS.md) says what a fork may and may not call itself. What the app does and does not send anywhere is written down in [PRIVACY.md](https://github.com/tonygorb/scenri/blob/main/PRIVACY.md).
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
package/dist/serve.js
CHANGED
|
@@ -1271,7 +1271,7 @@ function createCatalogStore(db) {
|
|
|
1271
1271
|
// ../core/src/engine.ts
|
|
1272
1272
|
var REFERENCE_ROLE_DIRECTIVE = {
|
|
1273
1273
|
product: "the exact product \u2014 preserve its label, shape, colors and design faithfully; do not redesign it",
|
|
1274
|
-
character: "the exact person \u2014
|
|
1274
|
+
character: "the exact person \u2014 match their face, facial structure, skin, hair and build exactly; their clothing, pose and background are capture context, not styling to reproduce",
|
|
1275
1275
|
brand: "the brand's own mark \u2014 if the direction calls for the mark to appear, reproduce it exactly as drawn, same colours, letterforms and proportions; otherwise take only its colour and treatment, and never its subject, geometry or composition",
|
|
1276
1276
|
scene: "a reference for the environment and light only \u2014 take no subject, product or person from it",
|
|
1277
1277
|
composition: "a reference for framing, camera angle and pose only \u2014 take no subject, color, material or branding from it",
|
|
@@ -1280,7 +1280,7 @@ var REFERENCE_ROLE_DIRECTIVE = {
|
|
|
1280
1280
|
};
|
|
1281
1281
|
var EDIT_REFERENCE_ROLE_DIRECTIVE = {
|
|
1282
1282
|
product: "the exact product: keep or restore its label, shape and design faithfully",
|
|
1283
|
-
character: "the exact person: keep their face, hair and build faithfully",
|
|
1283
|
+
character: "the exact person: keep their face, facial structure, skin, hair and build faithfully; take no clothing, pose or background from this reference, and keep the source image's existing outfit unless the instruction changes it",
|
|
1284
1284
|
brand: "the brand's own mark: reproduce it exactly as drawn wherever it appears, never redrawn or re-lettered",
|
|
1285
1285
|
scene: "a reference for environment and light only",
|
|
1286
1286
|
composition: "a reference for framing and pose only",
|
|
@@ -1944,6 +1944,9 @@ function createRunner(opts = {}) {
|
|
|
1944
1944
|
});
|
|
1945
1945
|
}
|
|
1946
1946
|
async function probe() {
|
|
1947
|
+
if (process.env.SCENRI_NO_CODEX === "1") {
|
|
1948
|
+
return { ok: false, reason: NOT_INSTALLED_REASON, code: "not-installed" };
|
|
1949
|
+
}
|
|
1947
1950
|
if (!await exitedZero(["--version"])) {
|
|
1948
1951
|
return { ok: false, reason: NOT_INSTALLED_REASON, code: "not-installed" };
|
|
1949
1952
|
}
|
|
@@ -2487,7 +2490,14 @@ async function resolvePresenterImages(core, templatesRoot, presenter) {
|
|
|
2487
2490
|
const hash = core.images.save(png);
|
|
2488
2491
|
shots.push({ file: `asset:${hash}`, angle, locked: true });
|
|
2489
2492
|
}
|
|
2490
|
-
|
|
2493
|
+
if (!shots.length) return null;
|
|
2494
|
+
return {
|
|
2495
|
+
id: presenter.id,
|
|
2496
|
+
name: presenter.name,
|
|
2497
|
+
...presenter.identityNotes ? { identityNotes: presenter.identityNotes } : {},
|
|
2498
|
+
...presenter.negativeConstraints?.length ? { negativeConstraints: presenter.negativeConstraints } : {},
|
|
2499
|
+
shots
|
|
2500
|
+
};
|
|
2491
2501
|
}
|
|
2492
2502
|
async function brandJsonWithResolvedPresenters(core, templatesRoot, presenters, brandJson, tokens) {
|
|
2493
2503
|
const existing = brandJson?.characters ?? [];
|
|
@@ -2793,7 +2803,7 @@ function compileBrief(brief, ctx) {
|
|
|
2793
2803
|
attachments.push({ role: "character", id: c.id, label: c.name, hash: chash, essential: i === 0 });
|
|
2794
2804
|
});
|
|
2795
2805
|
personDirectives.push(
|
|
2796
|
-
"The attached person reference is the same person every time:
|
|
2806
|
+
"The attached person reference is the same person every time: match their face, facial structure, skin, hair and build exactly. Their outfit, pose, background and lighting are neutral studio capture conditions, not styling direction: dress and style them for this shot, to a commercial standard, following any wardrobe the direction itself specifies."
|
|
2797
2807
|
);
|
|
2798
2808
|
if (c.identityNotes) personDirectives.push(String(c.identityNotes));
|
|
2799
2809
|
if (c.negativeConstraints?.length)
|
|
@@ -2891,10 +2901,14 @@ function compileBrief(brief, ctx) {
|
|
|
2891
2901
|
const sceneCamera = inlineTemplates[0]?.camera?.trim() || ctx.template?.camera?.trim() || "";
|
|
2892
2902
|
const cameraDirectives = sceneCamera && !shotSpecifiesCamera(sentence) ? [`Camera for this shot: ${sceneCamera}`] : [];
|
|
2893
2903
|
const guard = scene ? sceneGuardDirectives({ hasProduct: !!productId, hasPerson }) : [];
|
|
2904
|
+
const pairDirectives = productId && hasPerson ? [
|
|
2905
|
+
"If the attached product is something a person wears, the presenter wears that exact product, with the rest of the outfit styled around it; otherwise the presenter presents or uses the product naturally."
|
|
2906
|
+
] : [];
|
|
2894
2907
|
const brandLines = brandRuleDirectives(ctx.brand);
|
|
2895
2908
|
const allDirectives = [
|
|
2896
2909
|
...productDirectives,
|
|
2897
2910
|
...personDirectives,
|
|
2911
|
+
...pairDirectives,
|
|
2898
2912
|
...otherDirectives,
|
|
2899
2913
|
...cameraDirectives,
|
|
2900
2914
|
...brandLines,
|
|
@@ -6524,6 +6538,27 @@ function registerImageRoutes(app, deps) {
|
|
|
6524
6538
|
|
|
6525
6539
|
// src/release/notes.data.ts
|
|
6526
6540
|
var RELEASES = [
|
|
6541
|
+
{
|
|
6542
|
+
version: "0.3.4",
|
|
6543
|
+
date: "2026-08-21",
|
|
6544
|
+
sections: [
|
|
6545
|
+
{
|
|
6546
|
+
heading: "Presenters",
|
|
6547
|
+
body: "A presenter's reference photos now define who they are, not what they wear. The neutral studio outfit from their reference set no longer follows them into finished shots; wardrobe comes from the shot, the product and the scene instead, and refining an image keeps the outfit it already has."
|
|
6548
|
+
},
|
|
6549
|
+
{
|
|
6550
|
+
heading: "Fixes",
|
|
6551
|
+
body: "Opening a presenter or scene you built yourself no longer freezes the app."
|
|
6552
|
+
}
|
|
6553
|
+
]
|
|
6554
|
+
},
|
|
6555
|
+
{
|
|
6556
|
+
version: "0.3.3",
|
|
6557
|
+
date: "2026-08-20",
|
|
6558
|
+
// Documentation only: the links on the npm package page were resolving
|
|
6559
|
+
// against the package folder and 404ing. Nothing inside the app changed.
|
|
6560
|
+
sections: []
|
|
6561
|
+
},
|
|
6527
6562
|
{
|
|
6528
6563
|
version: "0.3.2",
|
|
6529
6564
|
date: "2026-08-20",
|