@deepblend/dsh-blender-bundle 0.1.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 ADDED
@@ -0,0 +1,86 @@
1
+ # @deepblend/dsh-blender-bundle
2
+
3
+ The **installable composition** of DeepBlend Studio — a Blender 3D animation workbench for
4
+ [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), where **SceneSpec is the
5
+ source of truth and `.blend` is a compiled artifact**.
6
+
7
+ This is the directory the plugin list's entry points at, so here is what it is, and what it is
8
+ not.
9
+
10
+ ## Install
11
+
12
+ From source:
13
+
14
+ ```sh
15
+ dsh plugin --profile web add 'github:pearjelly/deep-blend#path:/packages/deepblend/bundle'
16
+ ```
17
+
18
+ Or from the prebuilt release artifact, which resolves nothing:
19
+
20
+ ```sh
21
+ dsh plugin --profile web add https://github.com/pearjelly/deep-blend/releases/latest/download/deepblend-bundle.tgz
22
+ ```
23
+
24
+ Then restart `dsh web`. A new session can select the **DeepBlend Studio** preset, and the
25
+ workbench appears in the sidebar.
26
+
27
+ ## What is in here
28
+
29
+ | file | what it is |
30
+ |---|---|
31
+ | `cordis.patch.yml` | the composition — four rows and the configuration they mount with |
32
+ | `lib/index.js` | exports `PATCH_FILE` and `ROW_IDS`; it exists so the package is a well-formed importable ESM package |
33
+ | `screenshots.json` | the storefront's screenshot manifest |
34
+
35
+ There is no runtime code in this package, and that is deliberate rather than an omission.
36
+
37
+ ## How it works
38
+
39
+ The patch mounts four rows:
40
+
41
+ | row | package | what it publishes |
42
+ |---|---|---|
43
+ | `deepblend-blender-runtime` | `@deepblend/dsh-blender-provider-local` | the Blender execution seam |
44
+ | `deepblend-blender-host` | `@deepblend/dsh-blender-host` | the business facade both planes read |
45
+ | `deepblend-blender-ui` | `@deepblend/dsh-blender-ui` | the browser-facing host half |
46
+ | `deepblend-blender-preset` | `@deepblend/dsh-blender-preset` | deploys the agent presets |
47
+
48
+ The model-visible tools are deliberately **not** registered here. A preset decides what one
49
+ session's model may see, so registering them in the host composition would hand the Blender
50
+ toolset to every session in the process — the last row is what delivers them, into
51
+ `<DSH_HOME>/.agent-presets/`, once per process.
52
+
53
+ ## Why this is not a meta-package
54
+
55
+ The plugin list does not list a bundle whose only content is a dependency list. This one is not
56
+ that, and the three checks are the market's own rather than our argument:
57
+
58
+ - **The gate requires this shape.** A submission must point at a package declaring `dsh.bundle`.
59
+ Exactly one package in this repository does, and it is this one — there is no other package the
60
+ gate would accept.
61
+ - **The shape is already listed.** Eight entries on the list point at a `packages/bundle`
62
+ directory, across six categories. One of them, `ayahunter/dsh-trail`, is a patch with a single
63
+ row and a single dependency and no source at all. This one composes four rows and configures
64
+ them.
65
+ - **It points at no other entry.** The six dependencies are this repository's own internal
66
+ modules — the contracts, the execution seam, the facade, the browser half, the tool plane and
67
+ the preset deployer — not other plugins on the list, so the double-counting that rule exists to
68
+ prevent cannot occur.
69
+
70
+ The full audit, with the readings behind it, is in
71
+ [`deepblend/docs/listing-entry.yml`](../../../deepblend/docs/listing-entry.yml) — the file the submitted entry
72
+ is generated from.
73
+
74
+ ## Where the product lives
75
+
76
+ | package | |
77
+ |---|---|
78
+ | [`../contracts`](../contracts) | SceneSpec, the schemas, the visual-issue vocabulary |
79
+ | [`../provider-local`](../provider-local) | controlled `bpy` execution and the SceneSpec compiler |
80
+ | [`../host`](../host) | the business facade: projects, revisions, render jobs, the visual loop |
81
+ | [`../ui`](../ui) | the workbench's host half and browser client |
82
+ | [`../tool`](../tool) | the model-visible tool plane |
83
+ | [`../preset`](../preset) | the agent presets and the deployer that installs them |
84
+
85
+ The repository root has the [full README](../../../README.md), and
86
+ [`deepblend/docs/`](../../../deepblend/docs) has the manuals.
@@ -0,0 +1,219 @@
1
+ # DeepBlend Studio Host Bundle — the HOST COMPOSITION layer (SPEC §4.1, §18).
2
+ #
3
+ # This patch adds one `insert` over the profile tree. It carries only
4
+ # process-level, cross-session capability:
5
+ #
6
+ # deepblend-blender-runtime → publishes `blenderRuntime` (Blender execution seam)
7
+ # deepblend-blender-host → publishes `blenderStudio` (business facade)
8
+ # deepblend-blender-ui → publishes `blenderUi` (browser-facing host half)
9
+ #
10
+ # The model-visible tool (`blender_capabilities`) deliberately does NOT live
11
+ # here. It belongs to the AGENT PRESET, because a preset decides what one
12
+ # session's model may see (SPEC §4.2, §4.3). Registering it here would expose
13
+ # the tool to every session in the process.
14
+ #
15
+ # ─────────────────────────────────────────────────────────────────────────────
16
+ # WHY THERE IS NOT ONE `!!js` EXPRESSION HERE
17
+ #
18
+ # The obvious spelling for a machine-dependent value would be
19
+ # `!!js process.env.X || …`, and it does NOT work. The loader interpolates `!!js`
20
+ # through
21
+ #
22
+ # new Function('ctx', 'with (ctx) { return eval(expr) }')
23
+ #
24
+ # evaluated against the **Loader context**, not the global object. `process` is
25
+ # not a Loader-context property, so any `!!js … process …` expression throws a
26
+ # ReferenceError at compose time. The failure is silent and deeply confusing:
27
+ # the row still mounts, the config key simply keeps its schema default, and the
28
+ # service then fails later at first use. That is exactly how `blenderPath` came
29
+ # up as the literal `'blender'` instead of the installed binary.
30
+ #
31
+ # `!!js` remains correct for expressions referencing only Loader-context values
32
+ # (which is how the shipped bundles use it). It is not a general escape hatch
33
+ # to Node globals.
34
+ #
35
+ # So this file cannot compute a path at all, and the answer M5 arrived at is that
36
+ # it should not try: every machine-dependent value is now a DEFAULT inside the
37
+ # package that owns it, computed from `DSH_HOME` or from the package's own
38
+ # location. See the note above the first row.
39
+ #
40
+ # OVERRIDING THESE VALUES: a row's `config` is replaced wholesale, not merged
41
+ # (measured — architecture-decisions D74), so the operator layer
42
+ # ($DSH_HOME/profiles/<name>/cordis.patch.yml) must restate every key it wants to
43
+ # keep. To pin storage to a directory of your own:
44
+ #
45
+ # - id: deepblend-blender-runtime
46
+ # config:
47
+ # timeoutMs: 180000
48
+ # maxOutputBytes: 1048576
49
+ # maxSpillBytes: 67108864
50
+ # executableAllowlist: []
51
+ # capabilitiesCacheMs: 60000
52
+ # keepWorkingDirectory: false
53
+ # workspaceRoot: /path/to/workspace
54
+ #
55
+ # - id: deepblend-blender-host
56
+ # config:
57
+ # maxPreviewSamples: 512
58
+ # maxVisualIterations: 5
59
+ # minVisualConfidenceForAutoFix: 0.8
60
+ # stopOnRepeatedIssueCount: 2
61
+ # visualReviewProvider: deepseek-official
62
+ # visualReviewModel: deepseek-flash
63
+ # visualReviewMaxTokens: 24000
64
+ # visualReviewViews: [active-camera, three-quarter, top, detail]
65
+ # finalRenderProfile: final
66
+ # maxFinalSamples: 4096
67
+ # ffmpegPath: ffmpeg
68
+ # ffprobePath: ffprobe
69
+ # encodeCrf: 18
70
+ # encodePreset: medium
71
+ # requireApprovalAboveFrames: 900
72
+ # progressPollMs: 1000
73
+ # reconcileOnStart: true
74
+ # workspaceRoot: /path/to/workspace
75
+ # ─────────────────────────────────────────────────────────────────────────────
76
+
77
+ - insert:
78
+ # Blender execution seam. `ctx.subprocess` is a declared injection, so this
79
+ # row parks in `waiting` — visibly — rather than failing later at first call.
80
+ #
81
+ # THIS ROW NAMES NO PATH, AND THAT IS THE POINT. Until M5 it carried five
82
+ # literal absolute paths — an absolute Blender binary, an absolute
83
+ # bootstrap.py, an absolute workspace root, that root's projects directory,
84
+ # and an allowlist entry — which meant the bundle composed rows pointing at
85
+ # one developer's home directory. On any other machine the product mounted,
86
+ # reported healthy, and then failed at first render; `--dump-config` looked
87
+ # correct throughout, because the values WERE what the file said.
88
+ #
89
+ # `!!js` could not be used to fix it: it is evaluated against the Loader
90
+ # context, where `process` does not exist (M0 §4.2, verified). So the defaults
91
+ # moved into the packages, where they are ordinary Node code that can look at
92
+ # its own location and at `DSH_HOME`:
93
+ #
94
+ # blenderPath 'auto' -> the managed install if present, else PATH
95
+ # bootstrapPath '' -> the copy shipped inside the provider package
96
+ # workspaceRoot '' -> <DSH_HOME>/deepblend (SPEC §17)
97
+ # projectsRoot '' -> <workspaceRoot>/projects (SPEC §13)
98
+ #
99
+ # An operator who wants a different location sets it in the operator layer
100
+ # ($DSH_HOME/profiles/<name>/cordis.patch.yml). Note that a layer's `config`
101
+ # REPLACES this one wholesale rather than merging into it — measured, see
102
+ # architecture-decisions D74 — so such a layer must restate every key it wants
103
+ # to keep.
104
+ #
105
+ # The portability of this file is asserted, not assumed:
106
+ # `contract/bundle-portability.test.mjs` fails on any absolute path here.
107
+ - id: deepblend-blender-runtime
108
+ name: '@deepblend/dsh-blender-provider-local'
109
+ config:
110
+ # A cold Blender launch plus one 64x36 render probe; measured ~0.4 s on
111
+ # the M0 machine, so 180 s is a generous ceiling rather than a real budget.
112
+ timeoutMs: 180000
113
+ maxOutputBytes: 1048576
114
+ maxSpillBytes: 67108864
115
+ # Extra executable allowlist roots beyond the built-in defaults
116
+ # (/Applications, /opt/homebrew/bin, /usr/local/bin, ~/Applications).
117
+ # An absolute `blenderPath` is trusted as a deliberate operator choice;
118
+ # this list matters when the path is a bare name resolved through PATH.
119
+ executableAllowlist: []
120
+ # Capabilities are stable within a session; re-probe explicitly by
121
+ # calling the tool with refresh=true.
122
+ capabilitiesCacheMs: 60000
123
+ # Retaining temp dirs is a debugging aid; off by default so a probe
124
+ # leaves no residue behind.
125
+ keepWorkingDirectory: false
126
+
127
+ # Business facade consumed by BOTH planes: the preset tool and the UI host
128
+ # half read the same authoritative answer (SPEC §14.3).
129
+ - id: deepblend-blender-host
130
+ name: '@deepblend/dsh-blender-host'
131
+ config:
132
+ # `projectsRoot` and `workspaceRoot` are deliberately absent for the same
133
+ # reason as the paths above; both rows resolve them from `DSH_HOME`, and
134
+ # because they resolve them through ONE helper they cannot disagree —
135
+ # which is what the paragraph that used to sit here asked a human to
136
+ # arrange ("MUST equal the runtime row's workspaceRoot"). A comment is not
137
+ # a constraint; a shared function is.
138
+ # Hard ceiling on preview cost, applied on top of the per-profile
139
+ # `maxSamplesBudget` (SPEC §15.4 render-cost threshold).
140
+ maxPreviewSamples: 512
141
+
142
+ # ── M2: the visual loop ──────────────────────────────────────────────
143
+ # SPEC §17 groups these under `agent`; they belong to the HOST because the
144
+ # loop they bound is host-owned (decision D34): the model asks for a review,
145
+ # and the host renders, measures, decides what to adopt and when to stop.
146
+ #
147
+ # Iteration cap. The reason this is a cap rather than a budget is that the
148
+ # loop already stops when it stops helping; this is the backstop for "it
149
+ # keeps finding something new".
150
+ maxVisualIterations: 5
151
+ # Findings below this confidence are reported to the model but never
152
+ # auto-applied (SPEC §15.1 "低置信度问题不自动修复").
153
+ minVisualConfidenceForAutoFix: 0.8
154
+ # Consecutive rounds an unchanged finding may recur before the loop stops
155
+ # (SPEC §12.3 "同一问题两轮未改善则停止自动迭代").
156
+ stopOnRepeatedIssueCount: 2
157
+ # Vision reviewer route. Measured in the M2 probe: `deepseek-flash` accepts
158
+ # images (inputModalities ["text","image"]). The catalog also carries a
159
+ # text-only `deepseek-v4-flash`, which would silently omit the sheet.
160
+ visualReviewProvider: deepseek-official
161
+ visualReviewModel: deepseek-flash
162
+ # Token budget for one reviewer call. Measured: with the full reviewer prompt
163
+ # and a 2x2 sheet, this model spends ~11 000 tokens on reasoning BEFORE it emits
164
+ # any text, so a budget sized for the answer alone ends the stream with no text
165
+ # at all — which downstream looks exactly like "reviewed it, found nothing".
166
+ visualReviewMaxTokens: 24000
167
+ # Views in the standard plan, in reading order. Four is the measured
168
+ # balance: a 2x2 sheet survives the request pixel budget at roughly 1:1 per
169
+ # tile, while nine tiles fall below the source resolution and turn a partial
170
+ # occlusion into an invisible one (`runtime-audit.md` §7.2.3).
171
+ visualReviewViews:
172
+ - active-camera
173
+ - three-quarter
174
+ - top
175
+ - detail
176
+
177
+ # Browser-facing host half. M0 serves the settings-card document; the Web
178
+ # Client Slot half arrives in M4.
179
+ - id: deepblend-blender-ui
180
+ name: '@deepblend/dsh-blender-ui'
181
+ config:
182
+ serveRoute: true
183
+
184
+ # ── THE AGENT-PRESET PLANE'S DELIVERABLE ────────────────────────────────
185
+ #
186
+ # The sixteen model-visible tools belong to an AGENT PRESET, not to this
187
+ # composition (SPEC §4.3): registering them here would hand the Blender
188
+ # toolset to every session in the process. So the preset is not a row of
189
+ # tools — it is a directory under `<DSH_HOME>/.agent-presets/`, and
190
+ # `dsh plugin add` installs a package rather than writing a user's preset
191
+ # root.
192
+ #
193
+ # Without this row the plugin installs and HALF works: the workbench appears,
194
+ # the project store serves, and no session can render anything, because the
195
+ # model has no `blender_*` tool to call. The package this row mounts ships
196
+ # the preset and installs it, which is what makes the one-line install the
197
+ # whole install. `dsh-expert-orchestrator` is the same shape on the plugin
198
+ # list.
199
+ #
200
+ # It deploys when the profile composes, idempotently, into
201
+ # `<DSH_HOME>/.agent-presets/` only — never the root itself, never another
202
+ # preset — and a home it cannot write is logged rather than thrown, because a
203
+ # convenience copy must not take a deployment down. `deploy: false` leaves a
204
+ # preset root that an operator manages themselves untouched.
205
+ #
206
+ # The two paths are EMPTY on purpose, for the reason the first row's comment
207
+ # gives: a machine-dependent value belongs in the package that owns it, where
208
+ # it is ordinary Node code that can look at `DSH_HOME` and at its own
209
+ # location. `''` means "the default", and the default is derived once in
210
+ # `@deepblend/dsh-blender-preset/deploy`.
211
+ - id: deepblend-blender-preset
212
+ name: '@deepblend/dsh-blender-preset'
213
+ config:
214
+ deploy: true
215
+ # Empty means every preset the package ships: a preset added to the
216
+ # package then arrives without a composition change.
217
+ presets: []
218
+ # Empty means `<DSH_HOME>/.agent-presets`.
219
+ target: ''
package/lib/index.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @deepblend/dsh-blender-bundle
3
+ *
4
+ * This package is **patch-only**: it contributes no runtime plugin, no service
5
+ * and no tool of its own. Its entire contribution is `cordis.patch.yml`,
6
+ * declared through `dsh.bundle.patch` and composed by the profile boot before
7
+ * the profile's own patch layer.
8
+ *
9
+ * The module exists so the package is a well-formed, importable ESM package —
10
+ * an `exports` map with no `.` entry makes `require.resolve('@deepblend/dsh-blender-bundle')`
11
+ * fail, which breaks tooling that introspects a profile's bundle list.
12
+ *
13
+ * The rows it inserts are:
14
+ * - `deepblend-blender-runtime` → `@deepblend/dsh-blender-provider-local`
15
+ * - `deepblend-blender-host` → `@deepblend/dsh-blender-host`
16
+ * - `deepblend-blender-ui` → `@deepblend/dsh-blender-ui`
17
+ */
18
+
19
+ /** The bundle's patch file, relative to the package root. */
20
+ export const PATCH_FILE = 'cordis.patch.yml'
21
+
22
+ /** Row ids this bundle inserts, in composition order. */
23
+ export const ROW_IDS = Object.freeze([
24
+ 'deepblend-blender-runtime',
25
+ 'deepblend-blender-host',
26
+ 'deepblend-blender-ui',
27
+ ])
28
+
29
+ export default { PATCH_FILE, ROW_IDS }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@deepblend/dsh-blender-bundle",
3
+ "version": "0.1.0",
4
+ "description": "DeepBlend Studio Host Bundle: composes the Blender runtime provider, host facade and UI host half, with default configuration.",
5
+ "main": "lib/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "default": "./lib/index.js"
9
+ },
10
+ "./package.json": "./package.json"
11
+ },
12
+ "files": [
13
+ "lib",
14
+ "cordis.patch.yml",
15
+ "screenshots.json"
16
+ ],
17
+ "dsh": {
18
+ "bundle": {
19
+ "patch": "./cordis.patch.yml"
20
+ }
21
+ },
22
+ "dependencies": {
23
+ "@deepblend/dsh-blender-contracts": "0.1.0",
24
+ "@deepblend/dsh-blender-host": "0.1.0",
25
+ "@deepblend/dsh-blender-preset": "0.1.0",
26
+ "@deepblend/dsh-blender-provider-local": "0.1.0",
27
+ "@deepblend/dsh-blender-tool": "0.1.0",
28
+ "@deepblend/dsh-blender-ui": "0.1.0"
29
+ },
30
+ "type": "module",
31
+ "license": "MIT",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/pearjelly/deep-blend.git"
35
+ }
36
+ }
@@ -0,0 +1,5 @@
1
+ [
2
+ "deepblend/docs/images/workbench-scene.png",
3
+ "deepblend/docs/images/render-contact-sheet.png",
4
+ "deepblend/docs/images/preview-compare.png"
5
+ ]