@hraness/slopcamera 3.3.6 → 3.5.0
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/README.md +30 -16
- package/apps/desktop/application/operation.ts +1 -1
- package/apps/desktop/cli/args.ts +1 -1
- package/apps/desktop/cli/capability-manifest.ts +13 -0
- package/apps/desktop/cli/commands.ts +8 -1
- package/apps/desktop/cli/help.ts +45 -10
- package/apps/desktop/cli/html-overlay-renderer.ts +16 -0
- package/apps/desktop/cli/menubar.ts +91 -15
- package/apps/desktop/cli/portable-surface.ts +2 -0
- package/apps/desktop/code/public.ts +1 -0
- package/apps/desktop/core/visual-style-look.ts +34 -0
- package/apps/desktop/dist/cli/main.js +338 -282
- package/apps/desktop/html-overlay/catalog.ts +1 -0
- package/apps/desktop/html-overlay/runtime.ts +15 -0
- package/apps/desktop/html-overlay/spatial.ts +10 -6
- package/apps/desktop/workflows/index.ts +1 -0
- package/dist/cli.js +6 -2
- package/dist/{index-sy1n4zfy.js → index-24w75s6a.js} +1 -1
- package/dist/{index-qtn3s421.js → index-8bhp7cj2.js} +1 -1
- package/dist/{index-10bz03js.js → index-jab2mg0s.js} +4 -3
- package/dist/{index-qry58nj2.js → index-mnp0bftq.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/operations.js +1 -1
- package/dist/vectorize/worker.js +1 -1
- package/dist/workflow.js +1 -1
- package/docs/README.md +4 -3
- package/examples/studio/vgpu/README.md +1 -1
- package/examples/style-portfolio/ANIMATION-STUDIES.md +34 -0
- package/examples/style-portfolio/FILM-PLATE.md +19 -0
- package/examples/style-portfolio/README.md +137 -0
- package/examples/style-portfolio/animation-studies.html +597 -0
- package/examples/style-portfolio/assets/instrument-serif-OFL.txt +93 -0
- package/examples/style-portfolio/assets/instrument-serif-latin-400.woff2 +0 -0
- package/examples/style-portfolio/build-gallery.ts +403 -0
- package/examples/style-portfolio/film-plate.html +76 -0
- package/examples/style-portfolio/finish-film.ts +152 -0
- package/examples/style-portfolio/market-street/README.md +43 -0
- package/examples/style-portfolio/market-street/mesh.py +145 -0
- package/examples/style-portfolio/market-street/scene.py +760 -0
- package/examples/style-portfolio/market-street/source.json +1 -0
- package/examples/style-portfolio/market-street/street_data.py +72 -0
- package/examples/style-portfolio/render-film-plate.ts +128 -0
- package/examples/style-portfolio/render.ts +89 -0
- package/examples/style-portfolio/verify-animation-source.mjs +94 -0
- package/package.json +14 -5
- package/skills/slopcamera/SKILL.md +13 -3
- package/skills/slopcamera/references/brand-illustrations.md +237 -0
- package/skills/slopcamera/references/gateway-media.md +6 -1
- package/skills/slopcamera/references/install.md +10 -1
- package/skills/slopcamera/references/music-video.md +5 -0
- package/skills/slopcamera/references/native-studio.md +4 -0
- package/skills/slopcamera/references/patent-drawings.md +4 -4
- package/skills/slopcamera/references/support.md +1 -1
- package/skills/slopcamera/references/vectorization.md +3 -1
- package/skills/slopcamera/references/visual-style-direction.md +143 -0
- package/src/cli.ts +28 -0
- package/src/code/public-operations.ts +9 -0
- package/src/index.ts +1 -0
- package/src/mcp/tools.ts +4 -0
- package/src/operations.ts +4 -0
- package/src/support.ts +1 -1
- package/src/vectorize/command.ts +6 -1
- package/src/vectorize/supervisor.ts +23 -3
- package/src/vectorize/tool.ts +8 -4
- package/src/version.ts +1 -1
- package/src/visual-style.ts +378 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Brand illustrations
|
|
2
|
+
|
|
3
|
+
Read this before you generate, trace, retouch, recolor, resize or ship any
|
|
4
|
+
product illustration or topic icon for a marketing page, docs landing, project
|
|
5
|
+
card or social card. A trace that "looks fine" at 448 px is not evidence. The
|
|
6
|
+
gate below is.
|
|
7
|
+
|
|
8
|
+
Scope: the **illustration** class of Slopcamera's two-class product artwork
|
|
9
|
+
(`slopcamera image icon --purpose illustration`), meaning marketing and topic
|
|
10
|
+
art shown at 24 to 160 px on Hraness sites. Marks (`--purpose mark`) keep their
|
|
11
|
+
own contract. Interface icons (nav, buttons, labels) stay on the stroke sprite
|
|
12
|
+
algal.computer uses (hugeicons, 24 viewBox, stroke 1.5, currentColor).
|
|
13
|
+
|
|
14
|
+
### The icon language
|
|
15
|
+
|
|
16
|
+
Every illustration in the portfolio is one family. Product identity comes from
|
|
17
|
+
the subject and the palette primary the site applies. It does not come from
|
|
18
|
+
per-product line weight, per-product ink or a different drawing style.
|
|
19
|
+
|
|
20
|
+
| Property | Rule |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| Frame | `viewBox="0 0 64 64"`, square. The subject's long side is 48 to 54 units, optically centered. The 5-unit margin is empty. |
|
|
23
|
+
| Line | Monoline centerline strokes: `fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"`. |
|
|
24
|
+
| Weights | Four tones and nothing else: **line** 2 u (the body of the drawing); **detail** 1.5 u (interior detail only, at most 25% of total line length); **accent** 3 u (at most one element, the focal point); **tint plane** `fill="currentColor" fill-opacity=".16"` (at most 2 paths, on the primary face only). No hairlines under 1.5 u. No solid fills except a tint plane. |
|
|
25
|
+
| Projection | Simple 30-degree isometric, or front orthographic for flat subjects such as a page, card or screen. Use one projection per site set. |
|
|
26
|
+
| Subject | One main object and at most one small secondary prop. At most 8 connected parts. No text, digits, letters, logos, hatching, texture, shading, gradients, shadows, ground planes, badges, frames or container tiles. |
|
|
27
|
+
| Spacing | Parallel strokes are at least 3 u apart (1.5 times the line). Closed counters are at least 6 u across. No stroke ends closer than 2 u to another stroke unless they join. |
|
|
28
|
+
| Color | `currentColor` only. No hex, rgb, named color, `<style>`, media query or `class` paint in the file. The site sets `color` (normally `var(--primary)`). |
|
|
29
|
+
| Markup | Only `<svg>`, `<g>`, `<path>`, `<circle>`, `<ellipse>`, `<rect>`, `<line>`, `<polyline>`. At most 24 elements and 400 path commands, 0.1-unit precision, 6 KB or less. No `mask`, `clipPath`, `filter`, `transform`, `vector-effect`, `use`, `image`, `style`, `script`, `href` or `url()`. No `data-slopcamera-line-weight`. |
|
|
30
|
+
|
|
31
|
+
#### Optical sizes
|
|
32
|
+
|
|
33
|
+
Stroke weight is fixed in frame units, so rendered weight scales with display
|
|
34
|
+
size. Three optical sizes keep the rendered line between about 1.2 and 3 CSS px,
|
|
35
|
+
roughly the square root of the size ratio to algal's 1.2 to 1.3 rem accent icons
|
|
36
|
+
(1.5/24 stroke gives 1.2 px at 19.2 px):
|
|
37
|
+
|
|
38
|
+
| Optical size | Display | Stroke | Detail length | Parts | Tint plane | File |
|
|
39
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
40
|
+
| `s` | 24 to 40 px | 3 u (1.1 to 1.9 px) | 100 to 280 u | 4 or fewer | none | `<id>.s.svg` |
|
|
41
|
+
| `m` (default) | 44 to 120 px | 2 u (1.4 to 3.75 px) | 160 to 460 u | 8 or fewer | 1 or fewer | `<id>.svg` |
|
|
42
|
+
| `l` | 128 px and up | 1.5 u (3 px and up) | 200 to 640 u | 10 or fewer | 2 or fewer | `<id>.l.svg` |
|
|
43
|
+
|
|
44
|
+
Below 24 px, use the product **mark**, never an illustration. Derive `s` from
|
|
45
|
+
`m` by pruning, never by scaling: drop detail strokes, merge near-parallel
|
|
46
|
+
lines, then re-stroke at 3 u.
|
|
47
|
+
|
|
48
|
+
#### Delivery
|
|
49
|
+
|
|
50
|
+
Sites render illustrations so the palette reaches them. Never ship them through
|
|
51
|
+
a bare `<img>` with a baked color.
|
|
52
|
+
|
|
53
|
+
1. **Preferred:** a generated per-site sprite, `/illustrations.svg`, with one
|
|
54
|
+
`<symbol id="<id>" viewBox="0 0 64 64">` per illustration, rendered as
|
|
55
|
+
`<svg class="hraness-illustration" data-size="m" aria-hidden="true"><use href="/illustrations.svg#<id>"/></svg>`.
|
|
56
|
+
`currentColor` inherits through `<use>`, the tint plane keeps its opacity,
|
|
57
|
+
and forced-colors mode works natively. This is the same sprite pattern
|
|
58
|
+
algal.computer uses for interface icons (`/icons.svg`).
|
|
59
|
+
2. **Fallback** where only an image URL is possible, such as Markdown or a CMS:
|
|
60
|
+
the design-kit mask utility (`.hraness-illustration` with a painted
|
|
61
|
+
mask layer) paints `var(--hraness-illustration-ink, var(--primary))`
|
|
62
|
+
through the SVG's alpha.
|
|
63
|
+
It follows the same structure as `.hraness-foil-mark`.
|
|
64
|
+
3. Size and color come from design-kit classes (`.hraness-illustration[data-size="s|m|l"]`).
|
|
65
|
+
Sites must not own a `.x-topic-icon { width: 88px … }` rule, an `opacity`,
|
|
66
|
+
a `filter: hue-rotate()` or an `invert()`.
|
|
67
|
+
4. Contrast: `--primary` against the surface the illustration sits on must
|
|
68
|
+
reach at least 3:1 (WCAG 1.4.11, non-text) in both schemes. Where a card
|
|
69
|
+
surface is tinted, set `--hraness-illustration-ink` to the palette's
|
|
70
|
+
strong-primary token instead of lowering opacity.
|
|
71
|
+
|
|
72
|
+
### Generate
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
slopcamera image icon '<subject>' --purpose illustration \
|
|
76
|
+
--concept '<one-sentence metaphor>' --size m --rounds 2 --output icons/<id>.svg --json
|
|
77
|
+
slopcamera image icon normalize icons/<id>.svg --size s --output icons/<id>.s.svg --json
|
|
78
|
+
slopcamera image icon check icons/ --json # gate every file; non-zero exit on any failure
|
|
79
|
+
slopcamera image icon sheet icons/ --palette <family> --output review.png # 32/64/88 px, light+dark
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
(`--concept`, `--size`, `normalize`, `check` and `sheet` are the proposed
|
|
83
|
+
additions. Today only `image icon` exists.)
|
|
84
|
+
|
|
85
|
+
1. **Concept first.** Turn the product verb into one physical object metaphor,
|
|
86
|
+
in one sentence. Write three candidates. Generate a gallery
|
|
87
|
+
(`slopcamera image gallery`) of the best two before spending icon rounds.
|
|
88
|
+
Reject metaphors another portfolio product already owns (see the shared
|
|
89
|
+
pool in the registry) unless you deliberately reuse the pooled file.
|
|
90
|
+
2. **Raster.** The prompt template below fixes ink, weight ratio, projection
|
|
91
|
+
and element budget. The model draws black on white. Color is never a
|
|
92
|
+
generation parameter.
|
|
93
|
+
3. **Normalize** (deterministic, local, no network): centerline re-trace to
|
|
94
|
+
2 u strokes, strip color to `currentColor`, reframe to 64, emit, then
|
|
95
|
+
re-measure. See "Normalization" below.
|
|
96
|
+
4. **Gate.** Hard numeric gate (below). A failure feeds a concrete correction
|
|
97
|
+
into the next round ("remove the 6 shelf slats; keep 2"), not a restyle.
|
|
98
|
+
5. **Critique.** The vision reviewer sees the **sheet**: 32, 64 and 88 px on
|
|
99
|
+
the target palette's light and dark surfaces, beside the site's other
|
|
100
|
+
illustrations, with the gate metrics printed underneath. A pass at 448 px
|
|
101
|
+
alone does not count.
|
|
102
|
+
6. **Register.** Record the file in the artwork registry with subject,
|
|
103
|
+
concept, sha256, gate version and metrics. Sites consume registry output.
|
|
104
|
+
They do not keep hand-copied SVGs.
|
|
105
|
+
|
|
106
|
+
#### Prompt template
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
A single product-brand line illustration of {subject}, shown as {concept}.
|
|
110
|
+
|
|
111
|
+
Drawing rules:
|
|
112
|
+
- Pure black (#000000) lines on a plain white (#FFFFFF) background. No other color, no gray.
|
|
113
|
+
- Every line has the same thickness, about 3% of the image width (about 32 px on a 1024 px image).
|
|
114
|
+
No thin detail lines. No filled or solid areas{accent_clause}.
|
|
115
|
+
- Simple 30-degree isometric view of one main object{prop_clause}. At most {max_parts} separate parts.
|
|
116
|
+
Draw as few lines as you can. Every line must still be clearly visible when the image is 64 px wide.
|
|
117
|
+
- Closed shapes are outlines, not filled. Leave at least one line-width of white between parallel lines.
|
|
118
|
+
- Round line ends and rounded corners.
|
|
119
|
+
- No text, numbers, letters, logos, hatching, texture, shading, gradients, shadows, floor, frame,
|
|
120
|
+
badge, tile or background shape.
|
|
121
|
+
- The object fills about 80% of the image and is centered.
|
|
122
|
+
{feedback_clause}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- `accent_clause`: empty by default. For a deliberate focal accent, use
|
|
126
|
+
`, except one small solid {part} no larger than a tenth of the drawing`.
|
|
127
|
+
The normalizer converts it to the tint plane.
|
|
128
|
+
- `prop_clause`: empty, or `, with one small {prop} beside it`.
|
|
129
|
+
- `max_parts`: 8 for `m`, 4 for `s`, 10 for `l`.
|
|
130
|
+
- `feedback_clause`: `The previous attempt was rejected. Change only this: {gate reason codes rendered as concrete edits}`.
|
|
131
|
+
|
|
132
|
+
Do not ask for brand color, "medium weight", "clean", "minimal" or "premium".
|
|
133
|
+
Those words do not constrain the raster. The numbers do.
|
|
134
|
+
|
|
135
|
+
#### Normalization
|
|
136
|
+
|
|
137
|
+
`slopcamera image icon normalize` makes weight and color properties of the
|
|
138
|
+
normalizer, not the image model:
|
|
139
|
+
|
|
140
|
+
1. Parse the SVG and reject forbidden content (list in "The icon language").
|
|
141
|
+
2. Rasterize its alpha on a **transparent** background, with the art's bounding
|
|
142
|
+
box fitted into 54 u inside a 64 u frame at 8 px/unit (512 by 512, pinned
|
|
143
|
+
librsvg/sharp).
|
|
144
|
+
3. Binarize at alpha 128 or more. Compute the Euclidean distance transform and a
|
|
145
|
+
Zhang–Suen skeleton.
|
|
146
|
+
4. Separate **masses** (ink more than 2 u from any background pixel, meaning a
|
|
147
|
+
region wider than 4 u). Keep at most 2 masses: trace their outer contours
|
|
148
|
+
with marching squares and emit them as tint planes
|
|
149
|
+
(`fill="currentColor" fill-opacity=".16"`). If masses exceed 12% of ink,
|
|
150
|
+
stop with `mass.excess`: the art is mark-weight and must be regenerated.
|
|
151
|
+
5. Turn the skeleton into a graph (junction and end pixels are nodes). Prune
|
|
152
|
+
spurs shorter than 2 u. Merge parallel chains closer than 3 u. Remove
|
|
153
|
+
components smaller than 1.5 u².
|
|
154
|
+
6. Trace each edge chain into a polyline, simplify it (Ramer–Douglas–Peucker
|
|
155
|
+
with epsilon 0.3 u), fit centripetal Catmull–Rom curves to cubic Béziers
|
|
156
|
+
with corner detection above 35 degrees, and join chains that meet at a node
|
|
157
|
+
of degree 2.
|
|
158
|
+
7. Emit at most 24 paths on `viewBox="0 0 64 64"` with the root attributes
|
|
159
|
+
`fill="none" stroke="currentColor" stroke-width="{2|3|1.5}" stroke-linecap="round" stroke-linejoin="round"`,
|
|
160
|
+
rounded to 0.1 u. Chains whose source width was under 1.8 u become detail
|
|
161
|
+
strokes (1.5 u, `m` and `l` only). One chain marked by the concept as the
|
|
162
|
+
accent becomes 3 u.
|
|
163
|
+
8. Re-render the emitted SVG and run the gate. Normalization never loosens a
|
|
164
|
+
threshold to pass.
|
|
165
|
+
9. Write a receipt: source sha256, output sha256, gate version, every metric
|
|
166
|
+
and the pruning counts.
|
|
167
|
+
|
|
168
|
+
Sketch (TypeScript, Bun; reuses Slopcamera's pinned sharp and has no new
|
|
169
|
+
native dependency):
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
export async function normalizeIllustration(svg: string, size: "s" | "m" | "l"): Promise<NormalizedIllustration> {
|
|
173
|
+
assertAllowedMarkup(svg) // forbidden tags/attrs/url()
|
|
174
|
+
const alpha = await renderAlphaFramed(svg, { frame: 64, art: 54, pxPerUnit: 8, background: "transparent" })
|
|
175
|
+
const ink = binarize(alpha, 128)
|
|
176
|
+
const dist = euclideanDistance(ink) // Felzenszwalb–Huttenlocher
|
|
177
|
+
const masses = regions(ink, (i) => dist[i] > 2 * 8)
|
|
178
|
+
if (share(masses, ink) > 0.12) throw gateError("mass.excess")
|
|
179
|
+
const graph = skeletonGraph(zhangSuen(ink))
|
|
180
|
+
prune(graph, { spurUnits: 2, mergeParallelUnits: 3, minComponentUnits2: 1.5 })
|
|
181
|
+
const chains = graph.chains().map((c) => fitCubic(rdp(c.points, 0.3 * 8), { cornerDeg: 35 }))
|
|
182
|
+
const out = emitSvg({
|
|
183
|
+
viewBox: "0 0 64 64",
|
|
184
|
+
stroke: { s: 3, m: 2, l: 1.5 }[size],
|
|
185
|
+
chains: classify(chains, dist), // line | detail | accent
|
|
186
|
+
tints: masses.slice(0, size === "s" ? 0 : size === "m" ? 1 : 2).map(marchingSquares),
|
|
187
|
+
precision: 0.1,
|
|
188
|
+
})
|
|
189
|
+
const metrics = await measureIllustration(out) // same code path as `icon check`
|
|
190
|
+
const problems = illustrationGate(metrics, size)
|
|
191
|
+
if (problems.length) throw gateError(problems)
|
|
192
|
+
return { svg: out, metrics, receipt: receiptFor(svg, out, metrics) }
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Re-stroking rescues drawings whose composition is sound but whose weight was
|
|
197
|
+
set by the image model. It cannot rescue mass art or over-detailed art; those
|
|
198
|
+
need regeneration from the prompt template with a smaller element budget.
|
|
199
|
+
|
|
200
|
+
#### Gate (version 1)
|
|
201
|
+
|
|
202
|
+
All metrics come from the framed render in normalization step 2, identical in
|
|
203
|
+
`image icon`, `icon check`, the jungle registry and CI.
|
|
204
|
+
|
|
205
|
+
| Code | Metric | Pass band (`m`) | `s` | `l` |
|
|
206
|
+
| --- | --- | --- | --- | --- |
|
|
207
|
+
| `weight.faint` / `weight.heavy` | median stroke width at skeleton points, (2·EDT − 1)/8 | 1.7 to 2.4 u | 2.6 to 3.4 u | 1.3 to 1.9 u |
|
|
208
|
+
| `weight.hairline` | share of skeleton under 1.0 u wide | 5% or less | 3% or less | 8% or less |
|
|
209
|
+
| `weight.mixed` | p90 stroke width while mass is above 2% | 3.0 u or less | 3.8 u or less | 3.0 u or less |
|
|
210
|
+
| `mass.excess` | ink more than 2 u from background, as share of ink | 12% or less | 0% | 12% or less |
|
|
211
|
+
| `coverage.sparse` / `coverage.dense` | Σα / frame area (transparent letterbox) | 0.09 to 0.22 | 0.08 to 0.20 | 0.07 to 0.22 |
|
|
212
|
+
| `detail.thin` / `detail.crowded` | skeleton length | 160 to 460 u | 100 to 280 u | 200 to 640 u |
|
|
213
|
+
| `parts.fragmented` | 8-connected components of 1 u² or more | 8 or fewer | 4 or fewer | 10 or fewer |
|
|
214
|
+
| `parts.specks` | components under 1.5 u² | 0 | 0 | 0 |
|
|
215
|
+
| `frame.aspect` | art bounding-box aspect | 1.6 or less | 1.4 or less | 1.8 or less |
|
|
216
|
+
| `svg.frame` | viewBox | `0 0 64 64` | same | same |
|
|
217
|
+
| `svg.color` | literal paint present, or `currentColor` absent | none / present | same | same |
|
|
218
|
+
| `svg.markup` | forbidden element or attribute | none | same | same |
|
|
219
|
+
| `svg.paths` / `svg.bytes` | element count / file size | 24 or fewer / 6 KB or less | 12 or fewer / 3 KB or less | 32 or fewer / 9 KB or less |
|
|
220
|
+
|
|
221
|
+
The bands hang together. At a 2 u line, 160 to 460 u of drawn length is 320 to
|
|
222
|
+
920 u² of ink, which is 0.08 to 0.22 of the 4096 u² frame. Coverage and detail
|
|
223
|
+
length therefore agree unless the art contains masses or hairlines, and those
|
|
224
|
+
have their own codes.
|
|
225
|
+
|
|
226
|
+
#### Review checklist
|
|
227
|
+
|
|
228
|
+
Run on the sheet, not on a single large render:
|
|
229
|
+
|
|
230
|
+
- [ ] Recognizable at 32 px without its label, on both light and dark surfaces.
|
|
231
|
+
- [ ] Line weight matches its neighbors on the site sheet. No drawing reads fainter or bolder than the rest.
|
|
232
|
+
- [ ] No stroke, gap or counter is narrower than the line.
|
|
233
|
+
- [ ] At most one accent and one tint plane, both on the focal element.
|
|
234
|
+
- [ ] Renders in the site's `--primary` through the sprite or mask, not in `#2474d4`. Contrast is 3:1 or better on the actual card surface.
|
|
235
|
+
- [ ] The concept matches the copy of the section it heads, and differs from other products' concepts unless it is pooled.
|
|
236
|
+
- [ ] `s` exists wherever the site shows the illustration at 40 px or less.
|
|
237
|
+
- [ ] `icon check` passes and the registry receipt is updated. There is no hand-edited copy in any site.
|
|
@@ -6,6 +6,11 @@ credential. It has no Slopcamera account, credential store, or hosted project.
|
|
|
6
6
|
|
|
7
7
|
## Start with the intended role
|
|
8
8
|
|
|
9
|
+
For a creative film or animation brief, use
|
|
10
|
+
[visual style direction](visual-style-direction.md) to translate the intended
|
|
11
|
+
look into concrete source, camera, movement, and finishing decisions. Keep a
|
|
12
|
+
literal prompt literal when that is what the user requested.
|
|
13
|
+
|
|
9
14
|
Clarify what the generated media needs to do in the final project:
|
|
10
15
|
|
|
11
16
|
- the subject or message;
|
|
@@ -131,7 +136,7 @@ Use [directing video](directing-video.md) for budgeted takes, accepted predecess
|
|
|
131
136
|
|
|
132
137
|
The small portable `slopcamera image generate '<prompt>' --output image.webp` command defaults to `recraft/recraft-v4.1-utility` and admits PNG/JPEG/WebP output. It is distinct from the local `ai` catalog workflow. Preserve literal prompts when requested, keep its output inside the intended workspace and never automatically retry a failed paid call. Its sibling `slopcamera image gallery '<subject>' --output-dir <directory>` shares that bounded model contract and composes several candidates into one review sheet; see [image galleries](image-galleries.md).
|
|
133
138
|
|
|
134
|
-
For product identity SVGs, `slopcamera image icon '<subject>' --purpose <mark|illustration> --output icon.svg` is the canned pipeline. `mark` produces a compact favicon/app/header mark: one to three bold masses in one ink, gated for 16–32 px recognition and low path count. `illustration` (the compatibility default) produces the related marketing illustration: simple isometric structure in one ink, gated against hairlines, dense fills, and detail lost at 64 px. Both run one style-locked Gateway raster through ink normalization, local tracing, and deterministic geometry gates. `--rounds 2` (the default) adds a purpose-specific vision critique that revises the prompt between attempts; `--rounds 1` is a single paid generation with no critique call. `--ink` overrides the ink color and `--keep-raster` retains the normalized line-art PNG beside the SVG.
|
|
139
|
+
For product identity SVGs, `slopcamera image icon '<subject>' --purpose <mark|illustration> --output icon.svg` is the canned pipeline. `mark` produces a compact favicon/app/header mark: one to three bold masses in one ink, gated for 16–32 px recognition and low path count. `illustration` (the compatibility default) produces the related marketing illustration: simple isometric structure in one ink, gated against hairlines, dense fills, and detail lost at 64 px. Both run one style-locked Gateway raster through ink normalization, local tracing, and deterministic geometry gates. `--rounds 2` (the default) adds a purpose-specific vision critique that revises the prompt between attempts; `--rounds 1` is a single paid generation with no critique call. `--ink` overrides the ink color and `--keep-raster` retains the normalized line-art PNG beside the SVG. For portfolio illustrations and topic icons, follow [brand illustrations](brand-illustrations.md): one shared line language, `currentColor` output, measured weight and density bands, and the site sheet review.
|
|
135
140
|
|
|
136
141
|
## Style recipes
|
|
137
142
|
|
|
@@ -14,7 +14,16 @@ command -v slopcamera
|
|
|
14
14
|
|
|
15
15
|
A restricted shell can omit package-manager paths. Check known host installation paths before declaring a tool unavailable. If Bun is genuinely absent, follow its official [installation guide](https://bun.sh/docs/installation) within the user’s authorized setup scope. Do not switch package managers or pipe an unreviewed installer into a shell.
|
|
16
16
|
|
|
17
|
-
Slopcamera installs from its verified release archive: `bun add --global https://github.com/hraness/slopcamera/releases/download/v3.
|
|
17
|
+
Slopcamera installs from its verified release archive: `bun add --global https://github.com/hraness/slopcamera/releases/download/v3.4.0/hraness-slopcamera-3.4.0.tgz`, then `slopcamera doctor --json`. Building from source is the contributor path. Historical Atet archives do not install the renamed CLI; never substitute `slopcamera` into an old archive URL.
|
|
18
|
+
|
|
19
|
+
If an update from a previous local archive reports `DependencyLoop`, use Bun's
|
|
20
|
+
[named tarball syntax](https://bun.com/docs/pm/cli/add#tarball-dependencies) with
|
|
21
|
+
the same verified archive:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
bun add --global @hraness/slopcamera@https://github.com/hraness/slopcamera/releases/download/v3.4.0/hraness-slopcamera-3.4.0.tgz
|
|
25
|
+
slopcamera --version
|
|
26
|
+
```
|
|
18
27
|
|
|
19
28
|
Use an existing compatible source build when available. Otherwise follow the [complete source-install guide](https://github.com/hraness/slopcamera/blob/main/docs/how-to/use-current-source.md): clone into a new directory, record its exact commit, install locked dependencies without lifecycle scripts, build the SDK and source CLI, then define the shell command against that checkout. A clone or skill installation alone does not install the executable. Do not alter an existing active checkout to satisfy this path.
|
|
20
29
|
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Render a music video from an authored scene
|
|
2
2
|
|
|
3
|
+
Choose the intended film or animation language with
|
|
4
|
+
[visual style direction](visual-style-direction.md) before authoring the scene.
|
|
5
|
+
The example dimensions below are an iteration setting; select native delivery
|
|
6
|
+
dimensions explicitly for the finished movie.
|
|
7
|
+
|
|
3
8
|
Use this workflow for a complete HTML or Three.js music video with a local track,
|
|
4
9
|
including dancing characters, changing landscapes, and musical light accents.
|
|
5
10
|
The export retains the source and creates an ordinary editable project with
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Direct a native film studio
|
|
2
2
|
|
|
3
|
+
For historical footage, physical materials, or a distinctive animation family,
|
|
4
|
+
establish [visual style direction](visual-style-direction.md) before choosing
|
|
5
|
+
lighting, camera, frame cadence, and finishing.
|
|
6
|
+
|
|
3
7
|
These commands require current source; check [installation](install.md) and `slopcamera help studio`.
|
|
4
8
|
|
|
5
9
|
Use `slopcamera studio` when the deliverable needs native Blender, CadQuery or Manim authoring. Keep the native source, caches and exact settings alongside review frames and final clips. This complements the existing Three/Spark scene and ordinary video-project workflows.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Prepare patent-style drawing sheets
|
|
2
2
|
|
|
3
3
|
Use `diagram sheets` for local monochrome vector drawing sheets with physical
|
|
4
|
-
page dimensions.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
page dimensions. The commands ship in Slopcamera v3.3.5 and later. Confirm
|
|
5
|
+
`slopcamera help diagram` lists them. If they are absent, the installed CLI is
|
|
6
|
+
older: follow [installation](install.md) to update it rather than inventing a
|
|
7
|
+
flag on ordinary diagram rendering.
|
|
8
8
|
|
|
9
9
|
## Preserve the authored content
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@ At an eligible human closeout, call `slopcamera support offer --json` once. Trea
|
|
|
6
6
|
around disabled state. Discovery on stderr is guidance, not an invitation claim.
|
|
7
7
|
|
|
8
8
|
For `kind:offer`, optionally say once: “You can support continued development of
|
|
9
|
-
Slopcamera’s local
|
|
9
|
+
Slopcamera’s local media tools.” Use the returned clean support link. This product
|
|
10
10
|
has no updates mailing list; do not collect an email or imply a subscription unlocks
|
|
11
11
|
features. Opening a link grants no authority to pay or create an account.
|
|
12
12
|
|
|
@@ -9,7 +9,9 @@ slopcamera image vectorize path/to/input.png --output path/to/input.svg --json
|
|
|
9
9
|
|
|
10
10
|
- Do not provide a credential for vectorization. The conversion keeps image bytes local; the initial tool provisioning can download a verified VTracer release.
|
|
11
11
|
- Do not redraw, relabel, crop, recolor, or simplify the subject beyond the
|
|
12
|
-
trace mechanics the command measures.
|
|
12
|
+
trace mechanics the command measures. Brand illustrations are the exception:
|
|
13
|
+
they are normalized to the shared line language in
|
|
14
|
+
[brand illustrations](brand-illustrations.md), not preserved at fidelity.
|
|
13
15
|
- Use `--duotone '#primary,#secondary'` only when the user explicitly asks for
|
|
14
16
|
that two-color adaptation.
|
|
15
17
|
- Preserve the emitted receipt in task output or an adjacent provenance record
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Direct a visual style
|
|
2
|
+
|
|
3
|
+
Use this reference when a scene needs a recognizable film or animation language,
|
|
4
|
+
or when producing a portfolio of distinct styles. The current-source `style`
|
|
5
|
+
catalog records reusable production decisions:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
slopcamera style list --json
|
|
9
|
+
slopcamera style show silent-actuality --json
|
|
10
|
+
slopcamera style show theatrical-cel --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
These profiles are art direction. They do not automatically transform an image,
|
|
14
|
+
replace a scene's materials, synthesize character animation, or certify historical
|
|
15
|
+
accuracy. Apply them through an appropriate renderer. The seven `html catalog`
|
|
16
|
+
profiles describe rendering tools; visual styles are a separate choice.
|
|
17
|
+
|
|
18
|
+
## Establish the picture before the finish
|
|
19
|
+
|
|
20
|
+
Write a short direction for the specific subject: setting and period, dominant
|
|
21
|
+
silhouette, foreground and distance planes, light source, camera position, one
|
|
22
|
+
readable action, and intended emotional rhythm. Keep the user's literal facts and
|
|
23
|
+
selected identity. Where invention is authorized, give the subject a concrete
|
|
24
|
+
setting and action instead of filling the prompt with quality adjectives.
|
|
25
|
+
|
|
26
|
+
Select the renderer that can produce the needed evidence:
|
|
27
|
+
|
|
28
|
+
| Picture requirement | Useful route |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Volumetric light, physical material, contact, perspective, architecture | Blender studio or Three scene |
|
|
31
|
+
| Drawn contours, held drawings, flat shadow shapes, graphic composition | Canvas/p5/Two HTML scene |
|
|
32
|
+
| Correct mathematical construction with deliberate teaching beats | Manim or checked deterministic Canvas geometry |
|
|
33
|
+
| Photographic or painted source assets that procedural geometry cannot supply | Authorized Gateway image generation, then reviewed composition |
|
|
34
|
+
| Photochemical finishing of an already convincing source | Existing ordered video-look effects, with restrained diffusion, grain, and vignette |
|
|
35
|
+
|
|
36
|
+
A photo-textured background does not make moving geometry photorealistic. A
|
|
37
|
+
Canvas material study does not demonstrate a physical clay simulation. Name the
|
|
38
|
+
actual method in a portfolio caption.
|
|
39
|
+
|
|
40
|
+
For creative delivery without specified dimensions, default to a native
|
|
41
|
+
3840×2160 master or an equivalent frame in the intended aspect ratio when the
|
|
42
|
+
renderer and source support it. Use explicit 1920×1080 previews for iteration.
|
|
43
|
+
Respect source-image dimensions and a provider's actual output limits; state a
|
|
44
|
+
lower native delivery clearly. Do not upscale a draft and call it native
|
|
45
|
+
high-resolution detail. A 4:3 silent-film composition and a low-resolution pixel
|
|
46
|
+
grid are deliberate exceptions to widescreen layout, not lower quality targets.
|
|
47
|
+
|
|
48
|
+
## Historical film
|
|
49
|
+
|
|
50
|
+
Choose a period and acquisition process before choosing damage. Early silent
|
|
51
|
+
actuality, a 1940s studio negative, postwar 16mm documentary, and a 1970s home movie
|
|
52
|
+
have different framing, motion, lighting, tonal latitude, and surface texture.
|
|
53
|
+
Use a dated primary reference for specific history and label uncertain geometry
|
|
54
|
+
or staging as interpretation. A source link beside an invented measurement does
|
|
55
|
+
not verify that measurement.
|
|
56
|
+
|
|
57
|
+
For an early street actuality:
|
|
58
|
+
|
|
59
|
+
- Research street furniture, transport, overhead utilities, paving, clothing,
|
|
60
|
+
signage, and the sightline. Keep source-supported facts separate from estimated
|
|
61
|
+
dimensions and compressed geography. Inspect generated images for contradictions
|
|
62
|
+
even when the prompt explicitly forbids them. Do not add a familiar landmark or lamp
|
|
63
|
+
merely because it exists there today.
|
|
64
|
+
- Stage a useful street depth: irregular storefront bays, window recesses,
|
|
65
|
+
cornices, varied reflectance, believable kerbs, contact shadows, and atmospheric
|
|
66
|
+
distance. Keep buildings from reading as identical extruded blocks.
|
|
67
|
+
- Put the camera on the actual support, such as a cable car at a plausible human
|
|
68
|
+
height and speed. Keep distant geography coherent as it moves. Avoid a drone
|
|
69
|
+
orbit, wide modern lens, skyline reveal, or floating gimbal unless the reference
|
|
70
|
+
supports it.
|
|
71
|
+
- Set capture cadence and playback cadence separately. A selected 16 fps
|
|
72
|
+
reconstruction is an artistic timing choice, not proof of the source camera's
|
|
73
|
+
exact crank speed. Hold drawings or photographed exposures deliberately; do
|
|
74
|
+
not interpolate every style to 60 fps.
|
|
75
|
+
- Plan the monochrome values in the source. Early film spectral response cannot
|
|
76
|
+
be recovered by desaturating arbitrary modern colors. Make roofs, skin,
|
|
77
|
+
clothing, sky, and street separate in luminance; tune this against the reference.
|
|
78
|
+
- Apply gentle highlight compression, optical softness, and restrained vignette
|
|
79
|
+
after the source works. Keep frame-varying grain fine enough to preserve facade
|
|
80
|
+
detail. Inspect wet surfaces, grain and stroke widths at final pixel size. Separate
|
|
81
|
+
visible sky brightness from ambient fill when a bright sky washes out contact
|
|
82
|
+
shadows; inspect material mapping on every visible face orientation.
|
|
83
|
+
Gate weave belongs to the entire image, not separate jittering objects.
|
|
84
|
+
Dirt and scratches are optional print wear, not the definition of old film.
|
|
85
|
+
|
|
86
|
+
Distinguish capture, print, restoration, and scan. A clean high-resolution scan
|
|
87
|
+
can retain fine texture and stable framing. Do not add heavy dust, crushed blacks,
|
|
88
|
+
sepia, random flicker, letterbox bars, or a fake timecode by habit. Keep invented
|
|
89
|
+
archival-looking footage labeled as an authored interpretation. A photographic
|
|
90
|
+
plate with optical movement is a still-image study, not evidence of independently
|
|
91
|
+
animated people, vehicles, or a historical event.
|
|
92
|
+
|
|
93
|
+
The Market Street example includes a source manifest and an explicitly compressed
|
|
94
|
+
street plan. Consult the Library of Congress film and SFMTA history linked in the
|
|
95
|
+
example before changing its dates or street equipment.
|
|
96
|
+
|
|
97
|
+
## Animation families
|
|
98
|
+
|
|
99
|
+
An influence such as *Akira* or 3Blue1Brown is useful reference language. Translate
|
|
100
|
+
it into mechanisms and create original subjects and compositions. The catalog
|
|
101
|
+
uses generic technique names so the direction is reusable beyond one reference.
|
|
102
|
+
|
|
103
|
+
| Family | Construct the image and movement | Reject at review |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| Theatrical cel | Painted depth planes; precise perspective; selective contour weight; solid shadow shapes; articulated motion; held poses and short accents; camera motion sampled independently | Glossy toy materials, uniform outline filters, idle motion everywhere |
|
|
106
|
+
| Watercolor storybook | Broad pigment washes, warm paper, lost edges, a focal patch of crisp ink, gentle overlapping action | A blur over vector art, evenly noisy outlines, identical texture on every object |
|
|
107
|
+
| Ink sketch | Confident primary contours, sparse searching lines, directional hatching, selected line boil tied to held drawings | Unstable silhouettes, crosshatching through highlights, whole-scene wobble |
|
|
108
|
+
| Rubber hose | Strong readable silhouette, curved limbs, arcs, anticipation, squash and stretch with volume awareness, clear contact | Random sine waves on every joint, sliding feet, impossible eye direction |
|
|
109
|
+
| Midcentury limited | Asymmetric geometry, restrained spot palette, texture fields, selective held animation, strong negative space | Full constant motion, muddy colors, ornamental texture obscuring the subject |
|
|
110
|
+
| Cut paper | Distinct cut contours, shallow layer separation, directional edge shadows, articulated pivots and reveal order | Universal blur, deep plastic bevels, disconnected shadows |
|
|
111
|
+
| Stop-motion clay | Fingerprint-scale surface, soft contact, slightly imperfect construction, intentionally stepped poses and weighted settling | A smooth wobbling sphere described as physical stop motion, glossy uniform skin |
|
|
112
|
+
| Pixel art | Explicit logical grid, limited palette, clustered shading, authored sprite poses, integer-aligned travel, nearest-neighbor integer scale | Blurred scaling, subpixel edges, unrestricted gradients, every object at a different pixel size |
|
|
113
|
+
| Rotoscope | Gesture and weight from coherent anatomy, restrained contour drift, distinct held silhouettes, consistent volume | Unmotivated jitter, bendy joints, inconsistent limb lengths |
|
|
114
|
+
| Engraving | Hatching follows form; line density describes value; leave highlights open; compose large black and white masses | Uniform screen-space stripe overlays or crushed unreadable detail |
|
|
115
|
+
| Mathematical explanation | State one claim, assign stable colors, construct the relation, pause at its implication, keep notation readable | Decorative formulas, mismatched axes, moving labels, false equality, a waveform inconsistent with its generators |
|
|
116
|
+
| Isometric design | Stable projection, consistent edge families, hierarchy through material and spacing, staged exploded movement | Conflicting vanishing points, changing scale, unrelated decorative labels |
|
|
117
|
+
| Clean motion | A small set of shapes, optical alignment, purposeful easing, pauses, consistent transformation rules | Continuous bouncing, gratuitous overshoot, generic orbiting particles |
|
|
118
|
+
|
|
119
|
+
Build the action from anticipation, main movement, follow-through, and a readable
|
|
120
|
+
hold when those suit the style. Offset secondary action; avoid identical phase on
|
|
121
|
+
every leaf or limb. Derive state from absolute frame time, with seeded variation
|
|
122
|
+
keyed to the object and exposure index. Keep stable construction randomness
|
|
123
|
+
separate from intentionally changing drawing or grain randomness. Seeking frames
|
|
124
|
+
in a different order must reproduce the same image.
|
|
125
|
+
|
|
126
|
+
## Review and retain
|
|
127
|
+
|
|
128
|
+
Review representative frames before a full render: establishing view, strongest
|
|
129
|
+
action, transition, and ending. Then inspect the encoded movie for timing,
|
|
130
|
+
flicker, texture shimmer, crop, strobing, text, and compression. Pixel-level
|
|
131
|
+
sharpness does not establish coherent art direction. A large output dimension
|
|
132
|
+
does not establish source detail.
|
|
133
|
+
|
|
134
|
+
For a portfolio, select different subjects and compositions that reveal each
|
|
135
|
+
technique. Include the editable sources, profile IDs, actual output dimensions,
|
|
136
|
+
render receipts, and honest renderer labels. Separate reusable direction from
|
|
137
|
+
scene-specific drawing code. A contact sheet supports visual comparison; it does
|
|
138
|
+
not replace checking motion. Preserve an old result when it explains a change.
|
|
139
|
+
|
|
140
|
+
Keep bounded render jobs and their original sources. Dense grain can make a
|
|
141
|
+
lossless intermediate exceed the existing media bound, especially at 4K. Shorten
|
|
142
|
+
the shot or split it into retained takes without weakening that boundary. Do not
|
|
143
|
+
retry an ambiguous native or paid generation before inspecting its retained state.
|
package/src/cli.ts
CHANGED
|
@@ -38,6 +38,7 @@ import { installSkill, type SkillScope, type SkillTarget } from "./skill-install
|
|
|
38
38
|
import { pathExists } from "./fs.js"
|
|
39
39
|
import { checkDrawingFile, renderDrawingFile, starterDrawingSource } from "./drawing.js"
|
|
40
40
|
import { SLOPCAMERA_VERSION } from "./version.js"
|
|
41
|
+
import { createVisualStyleDirection, getVisualStyleProfile, VISUAL_STYLE_PROFILES } from "./visual-style.js"
|
|
41
42
|
import { reportUsefulResult, type UsefulResultObserver } from "./support-completion.js"
|
|
42
43
|
import { runProductSupportCommand, showProductSupportInvitation, standaloneSupportEnvironment } from "./support.js"
|
|
43
44
|
|
|
@@ -62,6 +63,8 @@ Usage:
|
|
|
62
63
|
slopcamera image gallery <subject> --output-dir <directory> [--kind <${slopcameraGalleryKinds.join("|")}>]
|
|
63
64
|
[--count <1-${slopcameraGalleryLimits.candidates}>] [--vary <axis[=v1,v2][;axis...]>] [--candidates <file.json>]
|
|
64
65
|
[--model <provider/model>] [--cell <${slopcameraGalleryLimits.cellEdgeMin}-${slopcameraGalleryLimits.cellEdgeMax}>] [--tile|--no-tile] [--json]
|
|
66
|
+
slopcamera style list [--json]
|
|
67
|
+
slopcamera style show <id> [--json]
|
|
65
68
|
slopcamera code search [query] [--limit <number>]
|
|
66
69
|
slopcamera code execute <operation> --input <JSON>
|
|
67
70
|
slopcamera mcp --root <workspace>
|
|
@@ -370,6 +373,31 @@ export async function main(
|
|
|
370
373
|
args: readonly string[],
|
|
371
374
|
dependencies: SlopcameraCliDependencies = {},
|
|
372
375
|
): Promise<void> {
|
|
376
|
+
if (args[0] === "style") {
|
|
377
|
+
const [action, ...words] = args.slice(1)
|
|
378
|
+
const json = words.at(-1) === "--json"
|
|
379
|
+
const positionals = json ? words.slice(0, -1) : words
|
|
380
|
+
const log = dependencies.log ?? console.log
|
|
381
|
+
if (action === "list" && positionals.length === 0) {
|
|
382
|
+
log(json
|
|
383
|
+
? JSON.stringify({ schemaVersion: 1, styles: VISUAL_STYLE_PROFILES })
|
|
384
|
+
: ["Visual style foundations (authoring guidance; no effects are applied):",
|
|
385
|
+
...VISUAL_STYLE_PROFILES.map(style => `${style.id} ${style.name}\n ${style.summary}`),
|
|
386
|
+
"Use slopcamera style show <id> for palette, cadence, materials, delivery, and review criteria."].join("\n"))
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
if (action === "show" && positionals.length === 1 && !positionals[0]!.startsWith("-")) {
|
|
390
|
+
let style
|
|
391
|
+
try {
|
|
392
|
+
style = getVisualStyleProfile(positionals[0])
|
|
393
|
+
} catch {
|
|
394
|
+
throw new Error(`Unknown visual style: ${JSON.stringify(positionals[0]!.slice(0, 128))}. Use slopcamera style list.`)
|
|
395
|
+
}
|
|
396
|
+
log(json ? JSON.stringify({ schemaVersion: 1, style }) : createVisualStyleDirection(style.id))
|
|
397
|
+
return
|
|
398
|
+
}
|
|
399
|
+
throw new Error("Use slopcamera style list [--json] or slopcamera style show <id> [--json].")
|
|
400
|
+
}
|
|
373
401
|
if (args[0] === "diagram" && args[1] === "sheets") {
|
|
374
402
|
await runDrawingSheets(args.slice(2), dependencies)
|
|
375
403
|
return
|
|
@@ -304,6 +304,15 @@ export interface PortableSlopcameraOperationResultMap {
|
|
|
304
304
|
readonly "slopcamera.image.vectorize": SlopcameraImageVectorizeOutput
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
+
/**
|
|
308
|
+
* The typed portable projection: four of the six `slopcameraOperationCodes`.
|
|
309
|
+
* `slopcamera.image.icon` and `slopcamera.image.gallery` stay outside it on
|
|
310
|
+
* purpose. Each runs several paid Gateway calls and can publish more than one
|
|
311
|
+
* artifact, which the single-output, single-dispatch contract model here
|
|
312
|
+
* cannot express; they remain reachable through `executeSlopcameraOperation`,
|
|
313
|
+
* `execute_slopcamera`, and the CLI. Public copy cites this count, and
|
|
314
|
+
* `scripts/check-copy.ts` fails when the copy and this list disagree.
|
|
315
|
+
*/
|
|
307
316
|
export const PORTABLE_SLOPCAMERA_OPERATION_KINDS = Object.freeze([
|
|
308
317
|
"slopcamera.diagram.check",
|
|
309
318
|
"slopcamera.diagram.render",
|
package/src/index.ts
CHANGED
|
@@ -171,6 +171,7 @@ export * from "./operations.js"
|
|
|
171
171
|
export * from "./portable-capability-manifest.js"
|
|
172
172
|
export * from "./scene-gallery.js"
|
|
173
173
|
export * from "./studio/index.js"
|
|
174
|
+
export * from "./visual-style.js"
|
|
174
175
|
export * from "./workflow.js"
|
|
175
176
|
export type * from "./types.js"
|
|
176
177
|
export type {
|
package/src/mcp/tools.ts
CHANGED
|
@@ -158,6 +158,10 @@ function deepFreeze<T>(value: T): T {
|
|
|
158
158
|
return Object.freeze(value)
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* The complete MCP tool registry. Public copy cites its size, its scene-tool
|
|
163
|
+
* count, and its names; `scripts/check-copy.ts` fails when they disagree.
|
|
164
|
+
*/
|
|
161
165
|
export const slopcameraMcpTools: readonly McpToolDefinition[] = deepFreeze([
|
|
162
166
|
{
|
|
163
167
|
name: "check_diagram",
|
package/src/operations.ts
CHANGED
|
@@ -38,6 +38,10 @@ import {
|
|
|
38
38
|
type HostResourceLease,
|
|
39
39
|
} from "./host-resources.js"
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* The fixed semantic operation registry. Public copy cites its size and names;
|
|
43
|
+
* `scripts/check-copy.ts` fails when README, docs, or skills disagree with it.
|
|
44
|
+
*/
|
|
41
45
|
export const slopcameraOperationCodes = [
|
|
42
46
|
"slopcamera.diagram.check",
|
|
43
47
|
"slopcamera.diagram.render",
|
package/src/support.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
export const supportProfile = {
|
|
8
8
|
id: "slopcamera",
|
|
9
9
|
name: "Slopcamera",
|
|
10
|
-
valueProposition: "Support ongoing development of local
|
|
10
|
+
valueProposition: "Support ongoing development of local media tools for agents.",
|
|
11
11
|
updates: false,
|
|
12
12
|
} as const
|
|
13
13
|
|
package/src/vectorize/command.ts
CHANGED
|
@@ -16,7 +16,12 @@ const MAX_COMMAND_OUTPUT_BYTES = 64 * 1_024
|
|
|
16
16
|
const PRIMARY_OUTPUT_READ_BYTES = 64 * 1_024
|
|
17
17
|
const PRIMARY_OUTPUT_POLL_MS = 2
|
|
18
18
|
const PRIMARY_OUTPUT_EXIT_EMPTY_POLLS = 2
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Grace between SIGTERM and SIGKILL when a bounded command overruns. Callers
|
|
21
|
+
* that layer their own wall-clock budget above a bounded command must reserve
|
|
22
|
+
* at least this much, plus scheduling latency, so cleanup finishes inside it.
|
|
23
|
+
*/
|
|
24
|
+
export const TERMINATION_GRACE_MS = 50
|
|
20
25
|
const HARD_KILL_WAIT_MS = 500
|
|
21
26
|
const MAX_INHERITED_FILE_DESCRIPTORS = 16
|
|
22
27
|
|