@instruktlabs/kiln 1.0.0 → 1.2.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +60 -3
- package/CONTRIBUTING.md +16 -7
- package/README.md +95 -381
- package/dist/agent-run.mjs +220 -150
- package/dist/build.json +40 -28
- package/dist/cli.mjs +242 -163
- package/dist/mcp-engine.mjs +412 -154
- package/dist/mcp-server.mjs +1 -1
- package/docs/architecture.md +6 -3
- package/docs/chatgpt.md +20 -5
- package/docs/examples.md +40 -170
- package/docs/install.md +100 -35
- package/docs/migration.md +20 -0
- package/docs/sdk.md +49 -5
- package/docs/tools-operations.md +1529 -0
- package/lib/asset-widget-uri.d.ts +9 -0
- package/lib/asset-widget-uri.js +9 -0
- package/lib/cli-render-mode.js +10 -3
- package/lib/discovery/index.d.ts +1 -1
- package/lib/discovery/index.js +2 -2
- package/lib/discovery/portable.d.ts +9 -0
- package/lib/discovery/portable.js +6 -0
- package/lib/discovery/service.d.ts +3 -1
- package/lib/discovery/service.js +4 -2
- package/lib/engine-identity.d.ts +1 -1
- package/lib/engine-identity.js +1 -1
- package/lib/evaluator/isolation.js +19 -5
- package/lib/evaluator/probe-invariants.d.ts +11 -0
- package/lib/evaluator/probe-invariants.js +36 -0
- package/lib/evaluator/probe-worker.js +16 -4
- package/lib/loopback.d.ts +6 -0
- package/lib/loopback.js +6 -0
- package/lib/mcp-core.d.ts +210 -0
- package/lib/mcp-core.js +279 -0
- package/lib/mcp-engine.d.ts +59 -0
- package/lib/mcp-engine.js +289 -0
- package/lib/mcp-manifest.d.ts +15 -0
- package/lib/mcp-manifest.js +65 -0
- package/lib/mcp.d.ts +5 -0
- package/lib/mcp.js +2 -0
- package/lib/render-service-host.js +1 -1
- package/lib/tools/discovery.d.ts +1 -1
- package/lib/tools/discovery.js +11 -9
- package/lib/tools/materials.d.ts +1 -1
- package/lib/tools/materials.js +44 -14
- package/lib/tools/operation-contract.d.ts +8 -0
- package/lib/tools/operation-contract.js +37 -0
- package/lib/tools/operations.d.ts +3 -0
- package/lib/tools/operations.js +154 -0
- package/lib/tools/registry.d.ts +6 -2
- package/lib/tools/registry.js +71 -23
- package/package.json +23 -1
- package/plugin.json +1 -1
- package/plugins/kiln-engine/.claude-plugin/icon.png +0 -0
- package/plugins/kiln-engine/.claude-plugin/plugin.json +9 -3
- package/plugins/kiln-engine/PRIVACY.md +100 -0
- package/plugins/kiln-engine/README.md +103 -18
- package/plugins/kiln-engine/{scripts/setup-workspace.mjs → bin/kiln-setup-workspace.mjs} +37 -9
- package/plugins/kiln-engine/package-provenance.json +15 -8
- package/plugins/kiln-engine/plugin.json +10 -4
- package/plugins/kiln-engine/runtime.json +10 -1
- package/plugins/kiln-engine/skills/kiln-setup-workspace/SKILL.md +17 -18
- package/plugins/kiln-engine/skills/kiln-setup-workspace/references/plugin-install.md +28 -8
- package/plugins/kiln-engine/skills/kiln-setup-workspace/references/renderer-setup.md +11 -0
- package/scripts/create-workspace.mjs +71 -13
- package/scripts/workspace-config.mjs +239 -0
- package/scripts/workspace-project.mjs +384 -0
- package/scripts/workspace-transaction.mjs +504 -0
- package/skills/kiln-setup-workspace/SKILL.md +17 -18
- package/skills/kiln-setup-workspace/references/plugin-install.md +28 -8
- package/skills/kiln-setup-workspace/references/renderer-setup.md +11 -0
- package/src/cli-render-mode.ts +9 -9
- package/src/cli.ts +3 -3
- package/src/discovery/index.ts +2 -0
- package/src/discovery/portable.ts +9 -0
- package/src/discovery/service.ts +3 -1
- package/src/engine-identity.ts +1 -1
- package/src/evaluator/isolation.ts +27 -6
- package/src/evaluator/probe-invariants.ts +50 -0
- package/src/evaluator/probe-worker.ts +22 -4
- package/src/mcp-core.ts +3 -0
- package/src/mcp-engine.ts +11 -1
- package/src/mcp.ts +5 -0
- package/src/render-service-host.ts +1 -1
- package/src/tools/discovery.ts +20 -10
- package/src/tools/materials.ts +59 -15
- package/src/tools/operation-contract.ts +51 -0
- package/src/tools/operations.ts +177 -0
- package/src/tools/registry.ts +100 -20
|
@@ -232,14 +232,15 @@ async function installRuntime(data, pin, archive, archiveHash, options) {
|
|
|
232
232
|
|
|
233
233
|
export async function setupPluginWorkspace(options = {}) {
|
|
234
234
|
const harness = options.harness || 'claude';
|
|
235
|
-
if (!['claude', 'codex'].includes(harness)) throw new Error('Choose harness claude or codex.');
|
|
236
235
|
const mode = options.mode || 'create';
|
|
237
|
-
if (!['create', 'check', 'upgrade', 'repair'].includes(mode))
|
|
236
|
+
if (!['create', 'check', 'upgrade', 'repair', 'recover'].includes(mode))
|
|
238
237
|
throw new Error('Unknown workspace setup mode.');
|
|
238
|
+
if (mode === 'recover' && (options.adopt || options.skills))
|
|
239
|
+
throw new Error('Use --recover alone before retrying setup.');
|
|
239
240
|
if (!options.directory) throw new Error('Provide a workspace directory.');
|
|
240
241
|
if (
|
|
241
242
|
options.skills &&
|
|
242
|
-
(mode !== 'create' ||
|
|
243
|
+
((mode !== 'create' && !(mode === 'check' && options.adopt)) ||
|
|
243
244
|
!Array.isArray(options.skills) ||
|
|
244
245
|
options.skills.some((name) => !['compose', 'batch'].includes(name)))
|
|
245
246
|
)
|
|
@@ -251,6 +252,18 @@ export async function setupPluginWorkspace(options = {}) {
|
|
|
251
252
|
if (pin.name !== packageName) throw new Error(`The plugin must pin package ${packageName}.`);
|
|
252
253
|
if (typeof pin.version !== 'string' || !exactVersion.test(pin.version))
|
|
253
254
|
throw new Error('The plugin runtime needs an exact stable, rc.N or dev.N version.');
|
|
255
|
+
// New bundles derive adapters from their pinned engine's initializer. Keep the
|
|
256
|
+
// original two-client contract for older bundles that have no capability list.
|
|
257
|
+
const harnesses = pin.harnesses === undefined ? ['claude', 'codex'] : pin.harnesses;
|
|
258
|
+
if (
|
|
259
|
+
!Array.isArray(harnesses) ||
|
|
260
|
+
!harnesses.length ||
|
|
261
|
+
harnesses.some((name) => typeof name !== 'string' || !/^[a-z][a-z0-9-]{0,63}$/.test(name)) ||
|
|
262
|
+
new Set(harnesses).size !== harnesses.length
|
|
263
|
+
)
|
|
264
|
+
throw new Error('Invalid workspace harness capabilities in the plugin runtime pin.');
|
|
265
|
+
if (!harnesses.includes(harness))
|
|
266
|
+
throw new Error(`Choose a supported workspace harness: ${harnesses.join(', ')}.`);
|
|
254
267
|
const directory = await canonical(options.directory);
|
|
255
268
|
const data = await canonical(options.dataDirectory || defaultDataDirectory());
|
|
256
269
|
for (const [a, b] of [
|
|
@@ -260,7 +273,7 @@ export async function setupPluginWorkspace(options = {}) {
|
|
|
260
273
|
])
|
|
261
274
|
if (inside(a, b) || inside(b, a))
|
|
262
275
|
throw new Error('Keep workspace, runtime data and plugin cache in separate directories.');
|
|
263
|
-
if (mode === 'create' && (await exists(directory))) {
|
|
276
|
+
if (mode === 'create' && !options.adopt && (await exists(directory))) {
|
|
264
277
|
if (!(await lstat(directory)).isDirectory() || (await readdir(directory)).length)
|
|
265
278
|
throw new Error(
|
|
266
279
|
'The workspace destination must be an empty directory; no existing files were changed.',
|
|
@@ -273,13 +286,22 @@ export async function setupPluginWorkspace(options = {}) {
|
|
|
273
286
|
{ name: pin.name, version: pin.version },
|
|
274
287
|
archive,
|
|
275
288
|
archiveHash,
|
|
276
|
-
{ ...options, mode },
|
|
289
|
+
{ ...options, mode: mode === 'recover' ? 'check' : mode },
|
|
277
290
|
);
|
|
278
|
-
const { createWorkspace } = await import(
|
|
291
|
+
const { createWorkspace, workspaceSetupCapabilities } = await import(
|
|
279
292
|
pathToFileURL(join(runtime, 'scripts/create-workspace.mjs')).href
|
|
280
293
|
);
|
|
294
|
+
if (options.adopt && workspaceSetupCapabilities?.projectAdoption !== 1)
|
|
295
|
+
throw new Error(
|
|
296
|
+
'The pinned engine does not support project adoption. Use a plugin release that pins a supporting engine; no project files were changed.',
|
|
297
|
+
);
|
|
298
|
+
if (mode === 'recover' && workspaceSetupCapabilities?.recovery !== 1)
|
|
299
|
+
throw new Error(
|
|
300
|
+
'The pinned engine does not support project recovery. No project files were changed.',
|
|
301
|
+
);
|
|
281
302
|
const workspace = await createWorkspace(directory, harness, {
|
|
282
303
|
installation: runtime,
|
|
304
|
+
...(options.adopt ? { adopt: true } : {}),
|
|
283
305
|
...(mode === 'create' ? {} : { [mode]: true }),
|
|
284
306
|
...(options.skills ? { skills: options.skills } : {}),
|
|
285
307
|
});
|
|
@@ -302,9 +324,13 @@ export function parseSetupArguments(args) {
|
|
|
302
324
|
};
|
|
303
325
|
while (values.length) {
|
|
304
326
|
const flag = values.shift();
|
|
305
|
-
if (['--check', '--upgrade', '--repair'].includes(flag)) {
|
|
306
|
-
if (result.mode)
|
|
327
|
+
if (['--check', '--upgrade', '--repair', '--recover'].includes(flag)) {
|
|
328
|
+
if (result.mode)
|
|
329
|
+
throw new Error('Choose only one of --check, --upgrade, --repair or --recover.');
|
|
307
330
|
result.mode = flag.slice(2);
|
|
331
|
+
} else if (flag === '--adopt') {
|
|
332
|
+
if (result.adopt) throw new Error('Repeated option --adopt.');
|
|
333
|
+
result.adopt = true;
|
|
308
334
|
} else if (Object.hasOwn(valueFlags, flag)) {
|
|
309
335
|
const value = values.shift();
|
|
310
336
|
if (!value || value.startsWith('--')) throw new Error(`Missing value for ${flag}.`);
|
|
@@ -312,6 +338,8 @@ export function parseSetupArguments(args) {
|
|
|
312
338
|
result[valueFlags[flag]] = flag === '--skills' ? value.split(',') : value;
|
|
313
339
|
} else throw new Error(`Unknown option ${flag}.`);
|
|
314
340
|
}
|
|
341
|
+
if (result.mode === 'recover' && (result.adopt || result.skills))
|
|
342
|
+
throw new Error('Use --recover alone before retrying setup.');
|
|
315
343
|
return result;
|
|
316
344
|
}
|
|
317
345
|
|
|
@@ -323,7 +351,7 @@ if (
|
|
|
323
351
|
const options = parseSetupArguments(process.argv.slice(2));
|
|
324
352
|
if (options.help)
|
|
325
353
|
console.log(
|
|
326
|
-
'Usage: node
|
|
354
|
+
'Usage: node bin/kiln-setup-workspace.mjs <directory> [--harness NAME] [--skills compose,batch]\n node bin/kiln-setup-workspace.mjs <project-or-new-workspace> --adopt [--check]\n node bin/kiln-setup-workspace.mjs <managed-workspace> --check|--upgrade|--repair|--recover\nOptions: --data-dir <persistent-directory>, --archive <qualification.tgz>, --npm-cli <npm-cli.js>\nWorkspace adapters are declared by the pinned engine in runtime.json.',
|
|
327
355
|
);
|
|
328
356
|
else {
|
|
329
357
|
const result = await setupPluginWorkspace(options);
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"kind": "kiln-local-plugin",
|
|
4
|
-
"
|
|
4
|
+
"pluginVersion": "1.2.0",
|
|
5
|
+
"engineVersion": "1.2.0",
|
|
6
|
+
"executables": [
|
|
7
|
+
"bin/kiln-setup-workspace.mjs"
|
|
8
|
+
],
|
|
5
9
|
"files": {
|
|
6
|
-
".claude-plugin/
|
|
10
|
+
".claude-plugin/icon.png": "sha256:b4b651c402793b7e27cab780f04b14f80daec6d0cd5b7e4e90313930581a54e9",
|
|
11
|
+
".claude-plugin/plugin.json": "sha256:616a6a61da072fcfdd4d0e1cf513e0e91bf1e56fb61b9b02d23e72fa291556bc",
|
|
12
|
+
"bin/kiln-setup-workspace.mjs": "sha256:3d9a30236919a6ca91acb6b26f808cec442e6edc3dd88fe010645b010d76e838",
|
|
7
13
|
"LICENSE": "sha256:cdba278ebf1d6de618869936226bf03be4887179c128efc7aaa13d22034826a5",
|
|
8
|
-
"plugin.json": "sha256:
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"skills/kiln-setup-workspace/references/plugin-install.md": "sha256:
|
|
13
|
-
"skills/kiln-setup-workspace/
|
|
14
|
+
"plugin.json": "sha256:3437107d46ad4fef4a710a8e821e56b43894cc1722504fe4e8ff0120fa6a8d8d",
|
|
15
|
+
"PRIVACY.md": "sha256:5f58d981667e40441e21c2dec411f269a9a67a6141cec61976d27088fb12573b",
|
|
16
|
+
"README.md": "sha256:0b82e6eb8b679f8b991c1a5567957574ed7b3341a87ef989403e5521f83ab50e",
|
|
17
|
+
"runtime.json": "sha256:5ebac8387f4bedcc7cac02a36f73c5ffba969ce6c8c6e2b0e356ef569168d0a5",
|
|
18
|
+
"skills/kiln-setup-workspace/references/plugin-install.md": "sha256:c338fb792e7fad0364c3e1a13c94c506afa1395489ec1b6e83b36d04728935fb",
|
|
19
|
+
"skills/kiln-setup-workspace/references/renderer-setup.md": "sha256:b743b1b2827fa814385990e1e5b849391cb427413e9c016d273aa19cebd46031",
|
|
20
|
+
"skills/kiln-setup-workspace/SKILL.md": "sha256:65ed926b3503a33f4fe793e84e4a045ce36e3967f0e6b340e456a15dd010ce54"
|
|
14
21
|
}
|
|
15
22
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "kiln-engine",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"description": "Set up a local Kiln workspace to create, inspect and revise editable 3D assets with Claude Code or Codex.",
|
|
6
6
|
"author": {
|
|
7
|
-
"name": "Instrukt Labs"
|
|
7
|
+
"name": "Instrukt Labs",
|
|
8
|
+
"email": "support@instruktlabs.com"
|
|
8
9
|
},
|
|
9
10
|
"homepage": "https://github.com/instruktlabs/kiln",
|
|
10
11
|
"repository": "https://github.com/instruktlabs/kiln",
|
|
@@ -19,10 +20,14 @@
|
|
|
19
20
|
"extensions": {
|
|
20
21
|
"com.openai": {
|
|
21
22
|
"interface": {
|
|
22
|
-
"displayName": "Kiln
|
|
23
|
+
"displayName": "Kiln",
|
|
23
24
|
"shortDescription": "Create editable 3D assets in a local workspace",
|
|
24
25
|
"longDescription": "Install the pinned Kiln engine and set up a workspace with local MCP tools and maintained authoring skills. Your coding agent supplies the model.",
|
|
25
26
|
"developerName": "Instrukt Labs",
|
|
27
|
+
"websiteURL": "https://github.com/instruktlabs/kiln/tree/main/plugins/kiln-engine",
|
|
28
|
+
"supportURL": "https://github.com/instruktlabs/kiln/blob/main/plugins/kiln-engine/README.md#support-and-security",
|
|
29
|
+
"privacyPolicyURL": "https://github.com/instruktlabs/kiln/blob/main/docs/local-plugin-privacy.md",
|
|
30
|
+
"termsOfServiceURL": "https://github.com/instruktlabs/kiln/blob/main/LICENSE",
|
|
26
31
|
"category": "Developer Tools",
|
|
27
32
|
"capabilities": [
|
|
28
33
|
"Read",
|
|
@@ -30,7 +35,8 @@
|
|
|
30
35
|
],
|
|
31
36
|
"defaultPrompt": [
|
|
32
37
|
"Set up a Kiln workspace for this coding agent.",
|
|
33
|
-
"Check
|
|
38
|
+
"Check my existing Kiln workspace without changing it.",
|
|
39
|
+
"Upgrade my managed Kiln workspace while preserving my assets."
|
|
34
40
|
]
|
|
35
41
|
}
|
|
36
42
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kiln-setup-workspace
|
|
3
|
-
description:
|
|
3
|
+
description: Configure and verify Kiln in an existing project or a new asset workspace for the selected coding agent. Use before authoring when the project has no working kiln_workspace server or needs another agent integration; engine development stays in the engine checkout.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
kiln-workflow: workspace
|
|
@@ -18,15 +18,18 @@ Do not author assets inside the engine checkout. The authoring skills assume a w
|
|
|
18
18
|
|
|
19
19
|
## Create the workspace
|
|
20
20
|
|
|
21
|
-
When this skill comes from the **Kiln
|
|
21
|
+
When this skill comes from the **Kiln local plugin**, its plugin root contains `runtime.json` and `bin/kiln-setup-workspace.mjs` (plugin 1.0.0 used `scripts/setup-workspace.mjs`). Follow [plugin installation and upgrades](references/plugin-install.md) to install the pinned engine and configure a separate workspace. Do not run the checkout command below from a plugin cache. The plugin registers setup only; the workspace supplies its authoring skills and `kiln_workspace` server.
|
|
22
22
|
|
|
23
|
-
Choose an absolute path
|
|
23
|
+
Choose the user's existing project or an absolute path for a new workspace outside the engine installation. Check the installed initializer's `--help`: this setup version supports `--adopt`; older engines support only empty destinations. Upgrade an older installation explicitly before adopting a populated project.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
node scripts/create-workspace.mjs /absolute/
|
|
26
|
+
node scripts/create-workspace.mjs /absolute/project --adopt --harness claude --check
|
|
27
|
+
node scripts/create-workspace.mjs /absolute/project --adopt --harness claude
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
From an installed package,
|
|
30
|
+
From an installed package, use `kiln-init` with the same arguments. Check reports planned changes and exits 1 when changes are needed; it writes nothing. Adoption preserves existing instruction files, unrelated settings, assets and skills. Read the returned `instructions` file (`.kiln/AGENTS.md`) and `.kiln/START.md`, alongside the project's existing instructions. Conflicts stop setup before writes; do not delete or replace owner configuration to make the command pass.
|
|
31
|
+
|
|
32
|
+
Author, refine and QA skills are installed by default; `--skills compose,batch` adds the optional workflows. Use the agent selected by the user or current host; ask only when it is unknown. Repeat `--adopt --harness codex` (or another supported adapter) to add that integration around the same program store. It explicitly migrates a legacy managed workspace while preserving assets. A combination whose config formats conflict is reported before changes; do not force one client's configuration into another. The plain empty-directory setup command remains compatible with older workflows.
|
|
30
33
|
|
|
31
34
|
CLI/MCP workspaces use the shared skills under `skills/`. Kiln's optional built-in Strands agent adds its workflow internally, outside that directory. Do not copy its system prompt, native workflow skill or completion protocol into another harness's skills or instructions. This applies to manual setup and plugin installs too; the engine's `src/agent/` directory is not a skill source.
|
|
32
35
|
|
|
@@ -37,24 +40,18 @@ CLI/MCP workspaces use the shared skills under `skills/`. Kiln's optional built-
|
|
|
37
40
|
| `cursor-agent` | `cursor-agent` |
|
|
38
41
|
| `opencode` | `opencode` |
|
|
39
42
|
| `agy` | `node agy.mjs` |
|
|
40
|
-
| `codex` | `node codex.mjs` |
|
|
43
|
+
| `codex` | `codex` after project trust; `node codex.mjs "TASK"` for a headless run |
|
|
41
44
|
| `hermes` | `node hermes.mjs` |
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
Read `.kiln/START.md` for an adopted project, or `START.md` in a legacy workspace. Codex reads trusted project configuration from `.codex/config.toml`; its optional headless launcher supplies the same settings per invocation without relocating authentication. Antigravity and Hermes use their generated launchers for the measured workspace flow. Setup does not grant project trust or edit global credentials. Skill registration is client-specific: Claude uses `.claude/skills`, Codex uses `.agents/skills`, and OpenCode uses its configured skills path, all copied from the same maintained Kiln skills.
|
|
44
47
|
|
|
45
48
|
Hermes needs one user-level registration for the MCP server, because it has no project-scoped equivalent and no per-invocation flag for one. Its START.md prints the exact `hermes mcp add` command; offer to run it, and verify with `hermes mcp list`. Never redirect `HERMES_HOME` at the workspace: that one variable resolves the configuration path and the credential path together, so pointing it at a workspace leaves the run with no provider.
|
|
46
49
|
|
|
47
|
-
##
|
|
48
|
-
|
|
49
|
-
Setup asks for render mode `auto`: textured or metallic scenes use a compatible GPU service, starting one lazily when available. Ordinary untextured scenes with zero metalness and no advanced material extensions use CPU views, even with a GPU available. CPU views support silhouette, proportion and contact review, but cannot confirm PBR appearance. Use CLI `--render gpu` when material review is required, including roughness on nonmetallic surfaces.
|
|
50
|
-
|
|
51
|
-
The renderer code is included with Kiln; its native GPU dependency is optional at the Kiln package root. For material-dependent tasks, check `node kiln.mjs service status` before starting the authoring session. If dependencies are missing or incompatible, reinstall the official Kiln package with optional dependencies enabled. npm 11 may print an `install-scripts` warning for the optional `webgpu` package; its postinstall only clears the macOS download quarantine from the prebuilt Dawn binary the package ships, so Windows and Linux need nothing and the warning is not an install failure. Read `runtime` from `.kiln/workspace.json` to identify the installation. A source checkout uses `bun install --frozen-lockfile` at that root. Setup checks dependency resolution without loading native code; ready dependencies alone do not prove the device can render.
|
|
50
|
+
## Check rendering readiness
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
Setup selects render mode `auto`. Textured or metallic scenes use a compatible render service; plain scenes use CPU geometry views. CPU views cannot confirm PBR appearance. Check `node kiln.mjs service status` before material-dependent work and require a real `viewFidelity` result before claiming material evidence.
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
A `KILN_RENDER_PORT_URL` whose origin is exactly the shared local socket (`http://127.0.0.1:8000` by default) takes the local route: it starts on demand and restarts after an idle exit. For rendering on another device, configure the MCP server process's `KILN_RENDER_PORT_URL` and, when needed, `KILN_RENDER_TOKEN` through the chosen harness. CLI accepts `--render-port URL` and reads `KILN_RENDER_TOKEN`. Start a compatible Kiln renderer on that device; its wider bind requires `RENDER_SERVICE_TOKEN` unless an authenticated proxy is explicitly configured. Manage the remote service on its own device. Verify the selected route with capabilities and require an actual `viewFidelity` receipt for material evidence.
|
|
54
|
+
Read [local renderer setup](references/renderer-setup.md) when dependencies are missing, a service is unavailable, or the task uses a renderer on another device. It covers dependency repair, shared-service lifetime, reprobe and authenticated remote rendering. Do not replace an unknown listener or install dependencies merely to clear a diagnostic.
|
|
58
55
|
|
|
59
56
|
## Verify the loadout before authoring
|
|
60
57
|
|
|
@@ -97,7 +94,9 @@ node /current/kiln/scripts/create-workspace.mjs /absolute/empty-workspace --repa
|
|
|
97
94
|
|
|
98
95
|
Repair rewrites generated runtime paths only. It preserves copied skills, saved revisions and assets, refuses configuration that was edited by hand, and does not upgrade the skills.
|
|
99
96
|
|
|
100
|
-
For an existing workspace, stop its harness/MCP session and run setup from the desired installation with `--check`, then `--upgrade`. Check returns JSON and exits 1 when an update is required. Upgrade refreshes unchanged configuration, instructions and
|
|
97
|
+
For an existing workspace, stop its harness/MCP session and run setup from the desired installation with `--check`, then `--upgrade`. Check returns JSON and exits 1 when an update is required. Upgrade refreshes unchanged owned configuration, instructions and registered skill copies while preserving assets and source stores. Conflicting local edits stop the whole upgrade before writing. Adopted projects preserve unrelated configuration changes and leave pre-existing instruction files alone. Legacy instruction files without ownership hashes can require explicit resolution; preserve them before resolving the named conflict. Do not overwrite an edited file merely to clear a diagnostic.
|
|
98
|
+
|
|
99
|
+
If adopted-project setup stops partway through writing, it attempts rollback. When it reports recovery required, preserve the project and run `kiln-init /absolute/project --recover` after confirming setup has stopped. Recovery refuses conflicting edits and retains its private snapshots outside the project. Resolve named conflicts explicitly; do not delete a lock or journal to force another setup. Recovery is for interrupted setup, not a general asset backup.
|
|
101
100
|
|
|
102
101
|
New managed launchers reject runtime/skill mismatches before serving tools; older workspaces need this explicit check first. Restart the harness/MCP session after upgrading so cached tool schemas and instructions match. `--repair` alone does not refresh copied skills or a running session. For independent model evaluations, create a fresh workspace from the candidate.
|
|
103
102
|
|
|
@@ -105,4 +104,4 @@ Discovery replaces the removed `kiln_list_primitives` tool; its old `name`, `nam
|
|
|
105
104
|
|
|
106
105
|
## What isolation means
|
|
107
106
|
|
|
108
|
-
A separate workspace limits task context
|
|
107
|
+
A separate workspace limits task context; an adopted project retains its existing application context and Git repository. Neither is an operating-system sandbox. User-level instructions, memory, authentication and filesystem permissions still apply. For comparing harnesses or models, use a fresh workspace and read `skills/kiln-batch-dispatch/references/clean-room-evaluation.md`, which covers inherited context and reporting trials.
|
|
@@ -4,19 +4,27 @@ The local `kiln-engine` plugin installs Kiln's exact pinned npm version and crea
|
|
|
4
4
|
an asset workspace. It carries setup guidance and a small installer; the engine,
|
|
5
5
|
source stores and authored assets live outside the plugin cache. It needs a
|
|
6
6
|
supported Node.js installation with npm, network access for first installation,
|
|
7
|
-
and no separate model API key.
|
|
7
|
+
and no separate model API key. Use it in Claude Code or Codex; it requires a local
|
|
8
|
+
shell and persistent filesystem and is not a Claude chat or Cowork plugin.
|
|
8
9
|
|
|
9
10
|
Resolve the plugin root from this installed skill's absolute path: it is two
|
|
10
11
|
directories above `skills/kiln-setup-workspace`. Confirm `runtime.json` and
|
|
11
|
-
`
|
|
12
|
+
`bin/kiln-setup-workspace.mjs` exist there. Do not assume plugin path variables are
|
|
12
13
|
available in an ordinary shell, and do not substitute an engine checkout.
|
|
13
14
|
|
|
15
|
+
Plugin version 1.0.0 used `scripts/setup-workspace.mjs`; if using that older
|
|
16
|
+
installation, confirm and use that file instead. Plugin and engine versions are
|
|
17
|
+
independent. `runtime.json` always names the exact engine to install.
|
|
18
|
+
|
|
14
19
|
For a fresh workspace, use an absolute empty destination outside both the plugin
|
|
15
|
-
and its runtime data directory. Select
|
|
16
|
-
|
|
20
|
+
and its runtime data directory. Select the current host or the user's stated
|
|
21
|
+
adapter. New bundles list the engine's supported adapters in `runtime.json`;
|
|
22
|
+
older bundles without that list accept `claude` or `codex` only. The plugin itself
|
|
23
|
+
is installed in Claude Code or Codex, but its helper can configure another adapter
|
|
24
|
+
supported by the pinned engine:
|
|
17
25
|
|
|
18
26
|
```sh
|
|
19
|
-
node "/absolute/plugin/
|
|
27
|
+
node "/absolute/plugin/bin/kiln-setup-workspace.mjs" "/absolute/my-assets" --harness codex
|
|
20
28
|
```
|
|
21
29
|
|
|
22
30
|
The installer verifies the package name and exact version from `runtime.json`.
|
|
@@ -27,11 +35,23 @@ or `$XDG_DATA_HOME/instruktlabs/kiln` on other systems, falling back to
|
|
|
27
35
|
Do not place it or the asset workspace inside a removable plugin version directory.
|
|
28
36
|
|
|
29
37
|
Read the returned workspace's `START.md`. Open Claude Code in that workspace, or
|
|
30
|
-
launch Codex there with `node codex.mjs
|
|
38
|
+
launch Codex there with `codex`. The `node codex.mjs "TASK"` launcher is for
|
|
39
|
+
headless execution with an explicit prompt. Accept the host's ordinary project/MCP
|
|
31
40
|
trust prompts, then call `kiln_discover({capabilities:true})` on `kiln_workspace`.
|
|
32
41
|
Compare its installation identity to `.kiln/workspace.json`; a config file alone
|
|
33
42
|
does not prove the server loaded. The plugin itself starts no global MCP server.
|
|
34
43
|
|
|
44
|
+
For an existing project, use a plugin whose helper advertises `--adopt` and whose
|
|
45
|
+
pinned engine supports project adoption. The published engine 1.0.0 predates this
|
|
46
|
+
feature. The helper checks the engine capability and refuses unsupported adoption
|
|
47
|
+
instead of silently falling back to empty-folder setup. Preview with
|
|
48
|
+
`--adopt --check --harness codex`, then apply with `--adopt --harness codex`.
|
|
49
|
+
Use the same path with another `--harness` to add an integration around the same
|
|
50
|
+
assets. Read the returned `instructions` path and `.kiln/START.md`; existing project
|
|
51
|
+
instruction files remain intact. The helper still leaves normal client trust
|
|
52
|
+
prompts to the host. No manual changes to a plugin's runtime pin are needed or
|
|
53
|
+
appropriate.
|
|
54
|
+
|
|
35
55
|
If the current workspace already has a working `kiln_workspace`, keep it. Do not
|
|
36
56
|
create a second server. Use its installed authoring skills, which come from its
|
|
37
57
|
engine version. The plugin supplies only setup, so authoring instructions are not
|
|
@@ -43,8 +63,8 @@ For an existing managed workspace, stop its harness session and run the new
|
|
|
43
63
|
plugin's helper with `--check`, then `--upgrade` when an update is intended:
|
|
44
64
|
|
|
45
65
|
```sh
|
|
46
|
-
node "/absolute/plugin/
|
|
47
|
-
node "/absolute/plugin/
|
|
66
|
+
node "/absolute/plugin/bin/kiln-setup-workspace.mjs" "/absolute/my-assets" --check
|
|
67
|
+
node "/absolute/plugin/bin/kiln-setup-workspace.mjs" "/absolute/my-assets" --upgrade
|
|
48
68
|
```
|
|
49
69
|
|
|
50
70
|
Check is read-only and reports a missing pinned engine without installing it.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Local renderer setup
|
|
2
|
+
|
|
3
|
+
Setup asks for render mode `auto`: textured or metallic scenes use a compatible GPU service, starting one lazily when available. Ordinary untextured scenes with zero metalness and no advanced material extensions use CPU views, even with a GPU available. CPU views support silhouette, proportion and contact review, but cannot confirm PBR appearance. Use CLI `--render gpu` when material review is required, including roughness on nonmetallic surfaces.
|
|
4
|
+
|
|
5
|
+
The renderer code is included with Kiln; its native GPU dependency is optional at the Kiln package root. For material-dependent tasks, check `node kiln.mjs service status` before starting the authoring session. If dependencies are missing or incompatible, reinstall the official Kiln package with optional dependencies enabled. npm 11 may print an `install-scripts` warning for the optional `webgpu` package; its postinstall only clears the macOS download quarantine from the prebuilt Dawn binary the package ships, so Windows and Linux need nothing and the warning is not an install failure. Read `runtime` from `.kiln/workspace.json` to identify the installation. A source checkout uses `bun install --frozen-lockfile` at that root. Setup checks dependency resolution without loading native code; ready dependencies alone do not prove the device can render.
|
|
6
|
+
|
|
7
|
+
Once dependencies are available, local CLI/MCP auto mode starts a managed service lazily for a view that needs PBR shading. Compatible clients share it; it survives the initiating session and exits after five minutes without admitted uploads, queued jobs or active renders. From the installation root, `node --import ./render-service/src/register-hooks.mjs render-service/src/server.mjs` starts a manual service that remains running while idle. It binds loopback; widening `HOST` requires `RENDER_SERVICE_TOKEN`.
|
|
8
|
+
|
|
9
|
+
`node kiln.mjs service status` reports installation, verified health and lifetime. `node kiln.mjs service start` joins a compatible service or starts a managed one the way an on-demand view does, and prints its port, renderer, pid, lifetime and build; it starts nothing when a stale, foreign or unknown listener holds the socket. After dependency repair or a cached startup failure, call `kiln_renderer({action:"reprobe"})` inside the MCP session to refresh its existing route. It neither installs dependencies nor starts a renderer; the next view starts one if needed. CLI `service reprobe` checks only its own process. Restart the session after changing Kiln, environment variables or credentials. Unknown or incompatible listeners are reported and left alone. `service stop` explicitly stops a verified local service. If no usable GPU is available, report the material-review limitation and continue on CPU views when that fits the task.
|
|
10
|
+
|
|
11
|
+
A `KILN_RENDER_PORT_URL` whose origin is exactly the shared local socket (`http://127.0.0.1:8000` by default) takes the local route: it starts on demand and restarts after an idle exit. For rendering on another device, configure the MCP server process's `KILN_RENDER_PORT_URL` and, when needed, `KILN_RENDER_TOKEN` through the chosen harness. CLI accepts `--render-port URL` and reads `KILN_RENDER_TOKEN`. Start a compatible Kiln renderer on that device; its wider bind requires `RENDER_SERVICE_TOKEN` unless an authenticated proxy is explicitly configured. Manage the remote service on its own device. Verify the selected route with capabilities and require an actual `viewFidelity` receipt for material evidence.
|
|
@@ -22,11 +22,24 @@ import { assertNodeRuntime } from '../src/runtime-support.mjs';
|
|
|
22
22
|
const installation = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
23
23
|
const quote = JSON.stringify;
|
|
24
24
|
const hash = (value) => createHash('sha256').update(value).digest('hex');
|
|
25
|
-
const harnesses = [
|
|
25
|
+
const harnesses = Object.freeze([
|
|
26
|
+
'claude',
|
|
27
|
+
'codex',
|
|
28
|
+
'opencode',
|
|
29
|
+
'hermes',
|
|
30
|
+
'agy',
|
|
31
|
+
'copilot',
|
|
32
|
+
'cursor-agent',
|
|
33
|
+
]);
|
|
34
|
+
export const workspaceSetupCapabilities = Object.freeze({
|
|
35
|
+
projectAdoption: 1,
|
|
36
|
+
recovery: 1,
|
|
37
|
+
harnesses,
|
|
38
|
+
});
|
|
26
39
|
/**
|
|
27
40
|
* Where the chosen harness looks for project skills, relative to the workspace, as
|
|
28
|
-
* measured on the installed CLIs (docs/harnesses.md).
|
|
29
|
-
*
|
|
41
|
+
* measured on the installed CLIs (docs/harnesses.md). Fresh-profile probes on
|
|
42
|
+
* 2026-10-07 load Claude skills from `.claude/skills`, not `.agents/skills`;
|
|
30
43
|
* codex, hermes, agy, copilot and cursor-agent name `.agents/skills`; opencode reads only
|
|
31
44
|
* the `skills.paths` its generated config names, which is `skills/` itself. One registry
|
|
32
45
|
* per harness: every copy is bytes an upgrade must track and a reader may edit.
|
|
@@ -304,7 +317,7 @@ try {
|
|
|
304
317
|
}
|
|
305
318
|
|
|
306
319
|
function startGuide(root, runtime, harness, nodeExecutable, server) {
|
|
307
|
-
const launchers = { agy: 'node agy.mjs',
|
|
320
|
+
const launchers = { agy: 'node agy.mjs', hermes: 'node hermes.mjs' };
|
|
308
321
|
const command = launchers[harness] ?? harness;
|
|
309
322
|
const launch =
|
|
310
323
|
harness === 'hermes'
|
|
@@ -573,13 +586,30 @@ export async function renderServiceNotice(runtime) {
|
|
|
573
586
|
/** Preflight first; create a complete project in a staging directory before installing it. */
|
|
574
587
|
export async function createWorkspace(directory, harness = 'claude', options = {}) {
|
|
575
588
|
let root = resolve(directory);
|
|
589
|
+
if (options.recover) {
|
|
590
|
+
if (options.repair || options.upgrade || options.check || options.adopt || options.skills)
|
|
591
|
+
throw new Error('Use --recover alone before retrying setup.');
|
|
592
|
+
const { recoverProjectEdits } = await import('./workspace-transaction.mjs');
|
|
593
|
+
return recoverProjectEdits(root, { stateDirectory: options.stateDirectory });
|
|
594
|
+
}
|
|
576
595
|
const runtime = await realpath(resolve(options.installation ?? installation));
|
|
577
596
|
if ([options.repair, options.upgrade, options.check].filter(Boolean).length > 1)
|
|
578
597
|
throw new Error('Choose only one of --repair, --upgrade or --check.');
|
|
579
|
-
if ((options.repair || options.upgrade || options.check) && options.skills)
|
|
598
|
+
if ((options.repair || options.upgrade || (options.check && !options.adopt)) && options.skills)
|
|
580
599
|
throw new Error('Maintenance does not change the installed skill selection.');
|
|
581
|
-
|
|
582
|
-
|
|
600
|
+
let previous;
|
|
601
|
+
if (options.adopt) {
|
|
602
|
+
const bytes = await workspaceFile(root, '.kiln/workspace.json');
|
|
603
|
+
if (bytes !== undefined) {
|
|
604
|
+
try {
|
|
605
|
+
previous = JSON.parse(bytes.toString('utf8'));
|
|
606
|
+
if (!previous || typeof previous !== 'object' || Array.isArray(previous)) throw new Error();
|
|
607
|
+
} catch {
|
|
608
|
+
throw new Error('Invalid Kiln workspace manifest; no files were changed.');
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
} else if (options.repair || options.upgrade || options.check)
|
|
612
|
+
previous = await readManifest(root);
|
|
583
613
|
// A read-only check validates the configured interpreter, not whichever supported
|
|
584
614
|
// Node the caller's shell selected. Setup/repair/upgrade deliberately repin it.
|
|
585
615
|
// A missing recorded executable remains drift; do not silently accept that case.
|
|
@@ -588,17 +618,20 @@ export async function createWorkspace(directory, harness = 'claude', options = {
|
|
|
588
618
|
options.check && typeof previous?.node === 'string' && existsSync(previous.node)
|
|
589
619
|
? previous.node
|
|
590
620
|
: realpathSync(process.execPath);
|
|
591
|
-
if (previous) harness = previous.harness;
|
|
621
|
+
if (previous && !options.adopt) harness = previous.harness;
|
|
592
622
|
if (!harnesses.includes(harness)) throw new Error(`Choose ${harnesses.join(', ')}.`);
|
|
593
623
|
const extras = options.skills ?? [];
|
|
594
624
|
if (extras.some((name) => !Object.hasOwn(optional, name)))
|
|
595
625
|
throw new Error('Optional skills: compose,batch.');
|
|
596
|
-
const
|
|
626
|
+
const previousSkills = previous?.skills ?? core;
|
|
597
627
|
if (
|
|
598
|
-
!Array.isArray(
|
|
599
|
-
|
|
628
|
+
!Array.isArray(previousSkills) ||
|
|
629
|
+
!core.every((name) => previousSkills.includes(name)) ||
|
|
630
|
+
new Set(previousSkills).size !== previousSkills.length ||
|
|
631
|
+
previousSkills.some((name) => ![...core, ...Object.values(optional)].includes(name))
|
|
600
632
|
)
|
|
601
633
|
throw new Error('Invalid workspace skill manifest.');
|
|
634
|
+
const skills = [...new Set([...previousSkills, ...extras.map((name) => optional[name])])];
|
|
602
635
|
const pkg = await preflightRuntime(runtime, skills, !options.check);
|
|
603
636
|
let exists = false;
|
|
604
637
|
try {
|
|
@@ -631,7 +664,7 @@ export async function createWorkspace(directory, harness = 'claude', options = {
|
|
|
631
664
|
}
|
|
632
665
|
if (inside(runtime, root) || inside(runtime, ancestor))
|
|
633
666
|
throw new Error('Choose a directory outside the Kiln installation.');
|
|
634
|
-
if (!previous && exists && (await readdir(root)).length)
|
|
667
|
+
if (!options.adopt && !previous && exists && (await readdir(root)).length)
|
|
635
668
|
throw new Error('The destination must be empty; no existing files were changed.');
|
|
636
669
|
const { files, store, server } = managedFiles(root, runtime, harness, nodeExecutable);
|
|
637
670
|
const manifest = {
|
|
@@ -660,6 +693,29 @@ export async function createWorkspace(directory, harness = 'claude', options = {
|
|
|
660
693
|
: undefined,
|
|
661
694
|
generated: Object.fromEntries(Object.entries(files).map(([name, body]) => [name, hash(body)])),
|
|
662
695
|
};
|
|
696
|
+
if (options.adopt || previous?.schemaVersion === 2) {
|
|
697
|
+
const { setupProject } = await import('./workspace-project.mjs');
|
|
698
|
+
return setupProject({
|
|
699
|
+
root,
|
|
700
|
+
runtime,
|
|
701
|
+
harness,
|
|
702
|
+
previous,
|
|
703
|
+
metadata: manifest,
|
|
704
|
+
exists,
|
|
705
|
+
options,
|
|
706
|
+
guide,
|
|
707
|
+
allowedHarnesses: harnesses,
|
|
708
|
+
projectFiles: (selected) => managedFiles(root, runtime, selected, nodeExecutable).files,
|
|
709
|
+
startGuide: (selected) => startGuide(root, runtime, selected, nodeExecutable, server),
|
|
710
|
+
skillFiles: async () => {
|
|
711
|
+
const result = {};
|
|
712
|
+
for (const skill of skills)
|
|
713
|
+
for (const name of Object.keys(await fileHashes(join(runtime, 'skills', skill))).sort())
|
|
714
|
+
result[`${skill}/${name}`] = await readFile(join(runtime, 'skills', skill, name));
|
|
715
|
+
return result;
|
|
716
|
+
},
|
|
717
|
+
});
|
|
718
|
+
}
|
|
663
719
|
if (previous && (options.upgrade || options.check))
|
|
664
720
|
return upgradeWorkspace(root, runtime, previous, manifest, files, options.check);
|
|
665
721
|
if (previous) {
|
|
@@ -773,7 +829,7 @@ if (isDirectSetupEntry()) {
|
|
|
773
829
|
const args = process.argv.slice(2);
|
|
774
830
|
if (args.includes('--help') || args.includes('-h')) {
|
|
775
831
|
console.log(
|
|
776
|
-
`Usage: kiln-init <empty-directory> [--harness ${harnesses.join('|')}] [--skills compose,batch]\n kiln-init <managed-workspace> --repair|--check|--upgrade`,
|
|
832
|
+
`Usage: kiln-init <empty-directory> [--harness ${harnesses.join('|')}] [--skills compose,batch]\n kiln-init <project-or-new-workspace> --adopt [--harness NAME] [--check]\n kiln-init <managed-workspace> --repair|--check|--upgrade\n kiln-init <project> --recover`,
|
|
777
833
|
);
|
|
778
834
|
} else {
|
|
779
835
|
const directory = args.shift();
|
|
@@ -786,6 +842,8 @@ if (isDirectSetupEntry()) {
|
|
|
786
842
|
if (flag === '--repair') options.repair = true;
|
|
787
843
|
else if (flag === '--upgrade') options.upgrade = true;
|
|
788
844
|
else if (flag === '--check') options.check = true;
|
|
845
|
+
else if (flag === '--adopt') options.adopt = true;
|
|
846
|
+
else if (flag === '--recover') options.recover = true;
|
|
789
847
|
else if (flag === '--harness' || flag === '--skills') {
|
|
790
848
|
const value = args.shift();
|
|
791
849
|
if (!value || value.startsWith('--')) throw new Error(`${flag} requires a value.`);
|