@punal_manalan/blender-project-harness 0.0.0-stage → 1.0.2
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/.kilo/agent/blender-grader.md +197 -0
- package/.kilo/agent/blender-worker.md +127 -0
- package/.kilo/blender-project-harness/config.example.json +71 -0
- package/.kilo/blender-project-harness/tools/harness/EXPECTED_FLOW.md +656 -0
- package/.kilo/blender-project-harness/tools/harness/blender-operations.mjs +882 -0
- package/.kilo/blender-project-harness/tools/harness/blender-operations.test.mjs +550 -0
- package/.kilo/blender-project-harness/tools/harness/blender.mjs +301 -0
- package/.kilo/blender-project-harness/tools/harness/blender.test.mjs +87 -0
- package/.kilo/blender-project-harness/tools/harness/cli.mjs +127 -0
- package/.kilo/blender-project-harness/tools/harness/documents.mjs +201 -0
- package/.kilo/blender-project-harness/tools/harness/download.mjs +94 -0
- package/.kilo/blender-project-harness/tools/harness/download.test.mjs +63 -0
- package/.kilo/blender-project-harness/tools/harness/engine.mjs +1866 -0
- package/.kilo/blender-project-harness/tools/harness/engine.test.mjs +2219 -0
- package/.kilo/blender-project-harness/tools/harness/intake.mjs +571 -0
- package/.kilo/blender-project-harness/tools/harness/intake.test.mjs +181 -0
- package/.kilo/blender-project-harness/tools/harness/package-lock.json +1227 -0
- package/.kilo/blender-project-harness/tools/harness/package.json +15 -0
- package/.kilo/blender-project-harness/tools/harness/plugin.mjs +550 -0
- package/.kilo/blender-project-harness/tools/harness/plugin.test.mjs +526 -0
- package/.kilo/blender-project-harness/tools/harness/proxy.mjs +222 -0
- package/.kilo/blender-project-harness/tools/harness/proxy.test.mjs +217 -0
- package/.kilo/blender-project-harness/tools/harness/scaffold.mjs +83 -0
- package/.kilo/blender-project-harness/tools/harness/scaffold.test.mjs +74 -0
- package/.kilo/blender-project-harness/tools/harness/server.mjs +24 -0
- package/.kilo/blender-project-harness/tools/harness/shell-policy.mjs +196 -0
- package/.kilo/blender-project-harness/tools/harness/shell-policy.test.mjs +68 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/ASSETS.md +29 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/DECISIONS.md +8 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/Goals/01-project-brief.md +71 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/Goals/README.md +17 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/INTAKE.md +8 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/README.md +57 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/REQUIREMENTS.md +64 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/REVIEW.md +29 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/References/README.md +18 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/Reviews/README.md +48 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/TASKSTRACKER.md +10 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/Tasks/README.md +4 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/Documents/WORKFLOW.md +36 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/README.md +130 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/README.md +31 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/audio/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/external/README.md +43 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/external/SOURCE_TEMPLATE.md +18 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/hdri/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/models/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/assets/textures/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/backups/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/backups/README.md +5 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/exports/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/exports/README.md +11 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/renders/README.md +7 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/renders/final/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/renders/wip/.gitkeep +0 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/scenes/README.md +10 -0
- package/.kilo/blender-project-harness/tools/harness/templates/project/scripts/README.md +16 -0
- package/.kilo/blender-project-harness/tools/harness/test-fixture.mjs +91 -0
- package/.kilo/blender-project-harness/tools/harness/workspace.mjs +30 -0
- package/.kilo/blender-project-harness/tools/harness/workspace.test.mjs +31 -0
- package/.kilo/blender-project-harness/tools/test_blender_tools.py +427 -0
- package/.kilo/plugins/blender-workflow.js +3 -0
- package/.kilo/skills/blender-assets/SKILL.md +99 -0
- package/.kilo/skills/blender-mcp/SKILL.md +147 -0
- package/.kilo/skills/blender-mcp/references/README.md +22 -0
- package/.kilo/skills/blender-mcp/references/animation.md +83 -0
- package/.kilo/skills/blender-mcp/references/bpy.md +97 -0
- package/.kilo/skills/blender-mcp/references/level-design.md +53 -0
- package/.kilo/skills/blender-mcp/references/materials.md +80 -0
- package/.kilo/skills/blender-mcp/references/retopology.md +104 -0
- package/.kilo/skills/blender-mcp/references/rigging.md +123 -0
- package/.kilo/skills/blender-mcp/references/scene.md +72 -0
- package/.kilo/skills/blender-project-goal/SKILL.md +115 -0
- package/.kilo/skills/blender-project-grading/SKILL.md +184 -0
- package/.kilo/skills/blender-project-readme/SKILL.md +46 -0
- package/.kilo/skills/blender-project-requirements/SKILL.md +84 -0
- package/.kilo/skills/blender-project-scaffold/SKILL.md +59 -0
- package/.kilo/skills/blender-project-workflow/SKILL.md +96 -0
- package/.kilo/skills/blender-subagents/SKILL.md +204 -0
- package/.kilo/skills/blender-workflow-harness/SKILL.md +187 -0
- package/AGENTS.md +234 -0
- package/Blender/README.md +30 -0
- package/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +368 -2
- package/THIRD_PARTY_NOTICES.md +51 -0
- package/bin/blender-project-harness.mjs +4 -0
- package/installer/cli.mjs +116 -0
- package/installer/install.mjs +325 -0
- package/installer/install.test.mjs +134 -0
- package/package.json +58 -6
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Workflow — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Mode: Unset
|
|
4
|
+
Selected: —
|
|
5
|
+
Last changed: {{DATE}}
|
|
6
|
+
|
|
7
|
+
## Current mode
|
|
8
|
+
|
|
9
|
+
- [ ] Fully Autonomous
|
|
10
|
+
- [ ] Partially Autonomous
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
- Fully Autonomous: proceed within confirmed requirements. Stop for blockers, destructive choices, or scope changes.
|
|
15
|
+
- Partially Autonomous: after every reviewable change (a bounded change with at least one apply),
|
|
16
|
+
seal, inspect with `look`, complete required grading and dispositions, then ask for approval or
|
|
17
|
+
revision direction before commit. Grader findings do not authorize corrections without that
|
|
18
|
+
direction.
|
|
19
|
+
- Kilo removes `question` during an active goal in either mode. The orchestrator follows
|
|
20
|
+
`blender-project-goal` for required-input handoffs, questions, objective updates, and resume; never
|
|
21
|
+
delegate goal commands to the user or repeat the stop procedure for already stopped work. Wait for
|
|
22
|
+
every required answer. Pause, cancellation, no answer, and manual editing keep work stopped.
|
|
23
|
+
- Commit through the harness `commit` action after each reviewed change: one scoped change per
|
|
24
|
+
commit, never one end-of-task dump. Manual project Git commits are blocked.
|
|
25
|
+
- Collect workflow and review answers after requirements confirmation and before scaffolding, then
|
|
26
|
+
persist their exact records before filling and starting the goal. Ask both modes before resuming a
|
|
27
|
+
genuine later return. Routine approval, clarification, and manual-edit pauses within the same task,
|
|
28
|
+
automatic goal turns, and compaction retain modes without reasking. The user may switch at any time.
|
|
29
|
+
- Require the final applicable `PASS` when grading is enabled and no genuine unresolved blocker or
|
|
30
|
+
major finding before completion. User approval does not waive those findings.
|
|
31
|
+
|
|
32
|
+
## Change log
|
|
33
|
+
|
|
34
|
+
| Date | Mode | Reason | Confirmed by |
|
|
35
|
+
|---|---|---|---|
|
|
36
|
+
| {{DATE}} | Unset | Project scaffolded. | Pending |
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Status: Draft
|
|
4
|
+
Last updated: {{DATE}}
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
|
|
8
|
+
{{DESCRIPTION}}
|
|
9
|
+
|
|
10
|
+
## What this project is
|
|
11
|
+
|
|
12
|
+
Describe the subject, the intended audience, and the visual result this project must deliver. Keep
|
|
13
|
+
this section short and concrete.
|
|
14
|
+
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
Confirmed scope and acceptance criteria: [`Documents/REQUIREMENTS.md`](Documents/REQUIREMENTS.md).
|
|
18
|
+
|
|
19
|
+
- [ ] Summarize the highest-priority confirmed requirements.
|
|
20
|
+
|
|
21
|
+
## Visual direction
|
|
22
|
+
|
|
23
|
+
- Style:
|
|
24
|
+
- Mood / references:
|
|
25
|
+
- Colour and lighting:
|
|
26
|
+
- Camera / framing:
|
|
27
|
+
- Scale and units:
|
|
28
|
+
|
|
29
|
+
## Deliverables
|
|
30
|
+
|
|
31
|
+
- Main Blender file: `{{PROJECT_SLUG}}.blend` (planned at project root until first save)
|
|
32
|
+
- Final renders: `renders/final/`
|
|
33
|
+
- Exports: `exports/`
|
|
34
|
+
- Documentation: `Documents/`
|
|
35
|
+
- External assets: `assets/external/`
|
|
36
|
+
|
|
37
|
+
## Project structure
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
{{PROJECT_NAME}}/
|
|
41
|
+
README.md
|
|
42
|
+
{{PROJECT_SLUG}}.blend
|
|
43
|
+
.gitignore
|
|
44
|
+
Documents/
|
|
45
|
+
README.md
|
|
46
|
+
REQUIREMENTS.md
|
|
47
|
+
WORKFLOW.md
|
|
48
|
+
REVIEW.md
|
|
49
|
+
ASSETS.md
|
|
50
|
+
DECISIONS.md
|
|
51
|
+
TASKSTRACKER.md
|
|
52
|
+
Tasks/
|
|
53
|
+
Goals/
|
|
54
|
+
Reviews/
|
|
55
|
+
References/
|
|
56
|
+
assets/
|
|
57
|
+
external/
|
|
58
|
+
textures/
|
|
59
|
+
hdri/
|
|
60
|
+
models/
|
|
61
|
+
audio/
|
|
62
|
+
renders/
|
|
63
|
+
final/
|
|
64
|
+
wip/
|
|
65
|
+
exports/
|
|
66
|
+
scenes/
|
|
67
|
+
scripts/
|
|
68
|
+
logs/
|
|
69
|
+
backups/
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Blender
|
|
73
|
+
|
|
74
|
+
- MCP port: owned by the workspace root `.kilo/kilo.jsonc`.
|
|
75
|
+
- Launch and stop with `blender_workflow` `launch`/`stop`; never invoke Blender from the shell.
|
|
76
|
+
- Before launch, require confirmed requirements, selected workflow and review records, and an active
|
|
77
|
+
filled goal. The harness validates project records, keeps the `.blend` inside this project, reads
|
|
78
|
+
the workspace MCP port, records the instance outside the repository, and rejects conflicting
|
|
79
|
+
workspace instances.
|
|
80
|
+
- Each launch writes `logs/blender-<timestamp>.log`; `logs/` is ignored.
|
|
81
|
+
- Main file: save the first scene as `{{PROJECT_SLUG}}.blend` in the project root. Before production
|
|
82
|
+
edits, verify MCP scene settings report that exact path; then replace the planned status above.
|
|
83
|
+
- Keep external paths relative (`//assets/...`); do not use absolute paths.
|
|
84
|
+
- Only one Blender project spawned by this workspace may be open at a time. Close the current one
|
|
85
|
+
before opening another.
|
|
86
|
+
|
|
87
|
+
## Workflow
|
|
88
|
+
|
|
89
|
+
- Record the selected autonomy mode in [`Documents/WORKFLOW.md`](Documents/WORKFLOW.md).
|
|
90
|
+
- Record review mode `Off`, `All`, or `Single` in [`Documents/REVIEW.md`](Documents/REVIEW.md);
|
|
91
|
+
rounds live in [`Documents/Reviews/`](Documents/Reviews/README.md).
|
|
92
|
+
- Collect both answers after requirements confirmation and before scaffolding; persist their exact
|
|
93
|
+
records after scaffolding and before filling and starting the goal. Launch only after that.
|
|
94
|
+
- After registration, workflow and review modes are frozen. A requested mode change stops production
|
|
95
|
+
for explicit re-registration; routine approval, clarification, or manual-edit pauses retain them.
|
|
96
|
+
- In Partially Autonomous mode, the agent seals, inspects, completes required grading, and obtains
|
|
97
|
+
approval or revision direction before the next reviewable change commits. In either mode, the agent
|
|
98
|
+
manages goal handoffs and continuation; users provide inputs and decisions.
|
|
99
|
+
- Require the saved inspected review render, current documents, and final applicable `PASS` when
|
|
100
|
+
grading is enabled before completion; no genuine unresolved blocker or major finding permits it.
|
|
101
|
+
|
|
102
|
+
## External assets
|
|
103
|
+
|
|
104
|
+
See [`Documents/ASSETS.md`](Documents/ASSETS.md) and [`assets/external/README.md`](assets/external/README.md).
|
|
105
|
+
|
|
106
|
+
- User files are brought in through `blender_workflow {action:"intake"}`; originals are never moved.
|
|
107
|
+
- No external assets yet. Replace this line with a summary when assets are added.
|
|
108
|
+
|
|
109
|
+
## Goals
|
|
110
|
+
|
|
111
|
+
Goal prompts live in [`Documents/Goals/`](Documents/Goals/). Multiple goals are allowed.
|
|
112
|
+
Identify the active goal's actual path; use it for grading rather than assuming the first brief.
|
|
113
|
+
|
|
114
|
+
- [`01-project-brief.md`](Documents/Goals/01-project-brief.md)
|
|
115
|
+
|
|
116
|
+
## References
|
|
117
|
+
|
|
118
|
+
- [`Documents/References/README.md`](Documents/References/README.md)
|
|
119
|
+
- Add links, moodboards, and source references here.
|
|
120
|
+
|
|
121
|
+
## Open questions
|
|
122
|
+
|
|
123
|
+
- [ ] Replace with unknown requirements or decisions.
|
|
124
|
+
|
|
125
|
+
## Next steps
|
|
126
|
+
|
|
127
|
+
- [ ] Persist the exact confirmed requirements and workflow/review answers collected before scaffold.
|
|
128
|
+
- [ ] Fill this README and the active goal, then start the goal before launch.
|
|
129
|
+
- [ ] Collect references and external assets.
|
|
130
|
+
- [ ] Build the scene, save and inspect a review render, and complete applicable grading and approvals.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Assets — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
| Folder | Use |
|
|
4
|
+
|---|---|
|
|
5
|
+
| `external/` | Third-party models, textures, HDRIs, audio, and libraries. Register in `Documents/ASSETS.md`. |
|
|
6
|
+
| `textures/` | Project-owned textures only. |
|
|
7
|
+
| `hdri/` | Project-owned environment maps only. |
|
|
8
|
+
| `models/` | Project-owned meshes and linked libraries only. |
|
|
9
|
+
| `audio/` | Project-owned sound effects, music, and voice assets only. |
|
|
10
|
+
|
|
11
|
+
Use relative paths from the `.blend` file (`//assets/...`). Do not embed absolute paths.
|
|
12
|
+
Store licensed third-party assets and their derivatives under `external/<source>/<asset>/`; modifying
|
|
13
|
+
an asset does not remove its source, licence, attribution, registration, or redistribution duties.
|
|
14
|
+
Keep `SOURCE.md` and verbatim `LICENSE.txt` beside each external asset and register every derivative.
|
|
15
|
+
|
|
16
|
+
Bring user files in with `blender_workflow {action:"intake"}`. Scan first, then copy inside an open
|
|
17
|
+
change; it hashes, classifies, deduplicates, writes source/licence sidecars, and updates the registers.
|
|
18
|
+
Use `download` only to fetch a public HTTPS asset into ignored staging. Do not ask the user to
|
|
19
|
+
create folders or copy files by hand. Browser/provider and user-assisted files return through
|
|
20
|
+
`intake` with their actual local path; never bypass authentication, CAPTCHA, or provider
|
|
21
|
+
restrictions.
|
|
22
|
+
|
|
23
|
+
External binaries under `assets/external/` are not committed unless `SOURCE.md` says
|
|
24
|
+
`Redistribution allowed: yes`. Sidecars, hashes, and metadata are committed. Media generation is
|
|
25
|
+
agent-owned and requires explicit permission before spending credits; pass the actual generated
|
|
26
|
+
file to `intake` with generated metadata.
|
|
27
|
+
|
|
28
|
+
Supported reviewed operations: `import_asset` for local GLB/glTF/FBX/OBJ/USD/`.blend`, `link_library`
|
|
29
|
+
for `.blend` link/append, `import_audio`, `image_texture`, `world_hdri`, `check_assets`,
|
|
30
|
+
`pack_assets`, and `export_scene`. Remote asset-library import and 3D generation remain blocked;
|
|
31
|
+
`download` and `intake` are the supported local staging path.
|
|
File without changes
|
package/.kilo/blender-project-harness/tools/harness/templates/project/assets/external/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# External Assets — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
This folder holds third-party assets. The default `.gitignore` excludes asset binaries so a project
|
|
4
|
+
does not accidentally commit large or non-redistributable files. Metadata stays tracked.
|
|
5
|
+
|
|
6
|
+
## Layout
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
assets/external/
|
|
10
|
+
<source-or-vendor>/
|
|
11
|
+
<asset-name>/
|
|
12
|
+
SOURCE.md
|
|
13
|
+
LICENSE.txt # mandatory verbatim licence terms; preserve originals too
|
|
14
|
+
<asset files>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Rules
|
|
18
|
+
|
|
19
|
+
- Use `intake` for user files. It copies accepted files here and writes `SOURCE.md`,
|
|
20
|
+
`LICENSE.txt`, and the `ASSETS.md` row. Use `download` only to stage an HTTPS file in `.temp`;
|
|
21
|
+
then pass it to `intake` with source and licence details.
|
|
22
|
+
- Never ask the user to create this folder tree or copy by hand. Original files are never moved.
|
|
23
|
+
- Copy applicable licence terms verbatim into `LICENSE.txt`; preserve original licence files too.
|
|
24
|
+
Record the licence source URL and required attribution exactly. Stop if terms are unavailable or
|
|
25
|
+
do not permit the intended use; do not invent or summarize them. Verify `SOURCE.md` and
|
|
26
|
+
`LICENSE.txt` are tracked before committing the project.
|
|
27
|
+
- Keep third-party originals and derivatives in this folder, including licensed assets. Register
|
|
28
|
+
derivatives and identify source and modifications; project modification does not remove licence duties.
|
|
29
|
+
- Record the asset in `../../Documents/ASSETS.md`.
|
|
30
|
+
- Do not commit an asset unless its licence allows redistribution. If it does, remove the ignore
|
|
31
|
+
rule for that exact path so the harness commit can stage it, and keep the licence beside it.
|
|
32
|
+
Force-add is unsupported; request reviewed tooling instead of using manual Git.
|
|
33
|
+
- For large redistributable assets, use Git LFS rather than committing raw binaries.
|
|
34
|
+
- Link or import with relative paths. Use the harness `import_asset` operation for local model files,
|
|
35
|
+
`link_library` for `.blend` libraries, `import_audio` for audio, and `image_texture`/`world_hdri`
|
|
36
|
+
for image assets. Check missing files with `check_assets` before delivery.
|
|
37
|
+
- Search tools can find assets, but remote asset-library import is not implemented. Use `download`
|
|
38
|
+
for an exact HTTPS URL, then `intake`; or supply the local file path directly to `intake`.
|
|
39
|
+
- Packing or embedding external data into a tracked or delivered `.blend` redistributes those bytes.
|
|
40
|
+
Verify the licence, attribution, and redistribution terms first, and record the packaging mode in
|
|
41
|
+
`../../Documents/ASSETS.md` and `SOURCE.md`.
|
|
42
|
+
- Pack external data only for delivery copies when permitted; keep an unpacked working copy when the
|
|
43
|
+
assets need editing.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Asset Source
|
|
2
|
+
|
|
3
|
+
- Asset:
|
|
4
|
+
- Source URL:
|
|
5
|
+
- Author / vendor:
|
|
6
|
+
- Licence:
|
|
7
|
+
- Licence source URL:
|
|
8
|
+
- Verbatim licence copy: LICENSE.txt (required; preserve original licence files too)
|
|
9
|
+
- Attribution required:
|
|
10
|
+
- Redistribution allowed:
|
|
11
|
+
- Packaging in .blend: linked / packed / embedded / none
|
|
12
|
+
- Local path:
|
|
13
|
+
- Imported into:
|
|
14
|
+
- Modifications:
|
|
15
|
+
- Original asset / derivative relationship:
|
|
16
|
+
- Acquisition instructions and file hashes:
|
|
17
|
+
- Date:
|
|
18
|
+
- Notes:
|
|
File without changes
|
|
File without changes
|
package/.kilo/blender-project-harness/tools/harness/templates/project/assets/textures/.gitkeep
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Exports — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Final interchange files (GLB, glTF, FBX, USD, OBJ) and other delivery outputs live here. Create them
|
|
4
|
+
with the reviewed `export_scene` operation inside a declared scene change, with the output path under
|
|
5
|
+
`exports/`. Record the export preset, scale, axis convention, and any known limitations in the project
|
|
6
|
+
README. Sidecar files such as OBJ `.mtl` or separate glTF buffers follow the same ownership and
|
|
7
|
+
licence rules as the main export.
|
|
8
|
+
|
|
9
|
+
Every export produces a harness receipt with format, project-relative path, bytes, SHA-256, source
|
|
10
|
+
scene, and signature check. Completion is denied for a missing or changed export. This validation is
|
|
11
|
+
separate from `check_assets`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Renders — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
- `final/` — reviewed renders that belong with the deliverable. Tracked.
|
|
4
|
+
- `wip/` — iteration renders and test frames. Ignored by git.
|
|
5
|
+
|
|
6
|
+
Use `//renders/...` paths relative to the `.blend` file. Record the render settings and the final
|
|
7
|
+
render names in the project README.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Scenes — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Save the main `.blend` at the project root as `{{PROJECT_SLUG}}.blend`. Multiple authored scenes
|
|
4
|
+
are supported inside that file. Use `create_scene`, `switch_scene`, `duplicate_scene`, and
|
|
5
|
+
`delete_scene`; `create_scene` supports `NEW`, `EMPTY` (Copy Settings), `LINK_COPY`, and
|
|
6
|
+
`FULL_COPY`. Existing operations accept an optional `scene` field. Declare exact scene names in
|
|
7
|
+
`begin`/`extend` or add them through scene operations, and give each shot scene its own camera.
|
|
8
|
+
A master Video Sequencer scene can use `scene_strip`. The harness seals and grades every declared
|
|
9
|
+
scene; a single-scene project may omit scene names and keeps the existing behavior. Linked `.blend`
|
|
10
|
+
libraries still use `link_library`. Use relative paths and document the primary scene.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Scripts — {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
Project-specific Blender Python source may live here. It is source-only: the harness never executes
|
|
4
|
+
it. Use relative paths from the project root or the `.blend` file and never hardcode machine-specific
|
|
5
|
+
paths.
|
|
6
|
+
|
|
7
|
+
Use `blender_workflow {action:"intake"}` with `kind:"script"` to copy `.py`/`.pyw` source here. The
|
|
8
|
+
harness accepts these files only under `scripts/` and records them in `Documents/INTAKE.md`.
|
|
9
|
+
|
|
10
|
+
Workspace automation scripts are a separate category. They may run only through the existing shell
|
|
11
|
+
command approval path, with the exact command, working directory, script SHA-256, reason, approval,
|
|
12
|
+
and outcome recorded. They are not a sandbox.
|
|
13
|
+
|
|
14
|
+
Any Blender Python execution requires a separately reviewed OS/VM isolation design. Do not use raw
|
|
15
|
+
Python, `--python`, `exec()`, or a hidden runner. Document each script's purpose and any approved
|
|
16
|
+
future invocation in this README.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { Harness, git } from './engine.mjs';
|
|
5
|
+
|
|
6
|
+
export function fixture(t, { partial = false, review = 'Off' } = {}) {
|
|
7
|
+
const tempBase = process.platform === 'win32' ? path.join(os.tmpdir(), 'kilo') : os.tmpdir();
|
|
8
|
+
const temp = fs.mkdtempSync(path.join(tempBase, 'workflow-integration-'));
|
|
9
|
+
t.after(() => fs.rmSync(temp, { force: true, recursive: true }));
|
|
10
|
+
const root = path.join(temp, 'workspace');
|
|
11
|
+
fs.mkdirSync(root);
|
|
12
|
+
const project = 'Blender/Test Project', scene = `${project}/scene.blend`, goal = 'Documents/Goals/01-test.md';
|
|
13
|
+
const write = (name, text) => {
|
|
14
|
+
const full = path.join(root, name);
|
|
15
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
16
|
+
fs.writeFileSync(full, text);
|
|
17
|
+
return full;
|
|
18
|
+
};
|
|
19
|
+
const objectiveText = '# Test Goal\n' + 'Confirmed fixture requirements and observable acceptance checks. '.repeat(4);
|
|
20
|
+
write(`${project}/README.md`, [
|
|
21
|
+
'# Fixture project',
|
|
22
|
+
'Status: Confirmed',
|
|
23
|
+
'Last updated: 2026-10-31',
|
|
24
|
+
'',
|
|
25
|
+
...['Purpose', 'What this project is', 'Requirements', 'Visual direction', 'Deliverables', 'Project structure', 'Blender', 'Workflow', 'External assets', 'Goals', 'References', 'Open questions', 'Next steps'].flatMap((name) => [`## ${name}`, `Fixture ${name.toLowerCase()}.`, '']),
|
|
26
|
+
].join('\n'));
|
|
27
|
+
write(`${project}/Documents/REQUIREMENTS.md`, [
|
|
28
|
+
'# Requirements',
|
|
29
|
+
'Status: Confirmed',
|
|
30
|
+
'Defined: 2026-10-31',
|
|
31
|
+
'Last updated: 2026-10-31',
|
|
32
|
+
'Confirmed: 2026-10-31',
|
|
33
|
+
'Confirmation: Confirm fixture requirements.',
|
|
34
|
+
'',
|
|
35
|
+
...['Core value', 'Confirmed requirements', 'Constraints', 'Deferred', 'Out of scope', 'Open questions', 'Research notes', 'Change log'].flatMap((name) => [`## ${name}`, `Fixture ${name.toLowerCase()}.`, '']),
|
|
36
|
+
].join('\n'));
|
|
37
|
+
write(`${project}/Documents/WORKFLOW.md`, [
|
|
38
|
+
'# Workflow',
|
|
39
|
+
`Mode: ${partial ? 'Partially' : 'Fully'} Autonomous`,
|
|
40
|
+
'Selected: 2026-10-31',
|
|
41
|
+
'Last changed: 2026-10-31',
|
|
42
|
+
'',
|
|
43
|
+
...['Current mode', 'Rules', 'Change log'].flatMap((name) => [`## ${name}`, `Fixture ${name.toLowerCase()}.`, '']),
|
|
44
|
+
].join('\n'));
|
|
45
|
+
write(`${project}/Documents/REVIEW.md`, [
|
|
46
|
+
'# Review Mode',
|
|
47
|
+
`Mode: ${review}`,
|
|
48
|
+
'Selected: 2026-10-31',
|
|
49
|
+
'Last changed: 2026-10-31',
|
|
50
|
+
'Single grader: visual',
|
|
51
|
+
'',
|
|
52
|
+
...['Modes', 'Change log'].flatMap((name) => [`## ${name}`, `Fixture ${name.toLowerCase()}.`, '']),
|
|
53
|
+
].join('\n'));
|
|
54
|
+
write(`${project}/Documents/ASSETS.md`, '# No external assets\n\n## Rules\n\nFixture asset rules.\n');
|
|
55
|
+
write(`${project}/Documents/DECISIONS.md`, '# Fixture decisions\n');
|
|
56
|
+
write(`${project}/Documents/TASKSTRACKER.md`, '# Task Tracker — Test Project\n\nStatus: Active\nLast updated: 2026-10-31\n\n## Tasks\n\n| Task | Kind | Change | Operation | Objects | Assigned | Child | State | Created | Finished | Result |\n|---|---|---|---|---|---|---|---|---|---|---|\n| — | — | — | — | — | — | — | — | — | — | — |\n');
|
|
57
|
+
const goalBody = objectiveText.replace(/^#\s+.*\r?\n/, '');
|
|
58
|
+
const objective = [
|
|
59
|
+
'# Goal: Fixture',
|
|
60
|
+
...['Mission', 'Project', 'Visual outcome', 'Scope', 'Deliverables', 'Acceptance', 'Workflow', 'Done'].flatMap((name) => [`## ${name}`, goalBody, '']),
|
|
61
|
+
].join('\n');
|
|
62
|
+
write(`${project}/${goal}`, objective);
|
|
63
|
+
write(scene, 'fixture blend bytes\n');
|
|
64
|
+
write(`${project}/Documents/Reviews/README.md`, '# Review Index\n\n## Index\n\nFixture index.\n\n## Rules\n\nFixture rules.\n');
|
|
65
|
+
write('.gitignore', '**/_evidence/**\n**/renders/wip/**\n/.kilo/blender-project-harness/config.json\n');
|
|
66
|
+
write(`${project}/.gitignore`, 'renders/wip/**\n');
|
|
67
|
+
const config = { blender_subagents: { workers: {
|
|
68
|
+
agent: 'blender-worker', provider: 'fixture-provider', model: 'fixture-model', variant: 'fixture-variant',
|
|
69
|
+
backup: { provider: 'backup-provider', model: 'backup-model', variant: 'backup-variant' },
|
|
70
|
+
max_minutes: 10, max_steps: 18, max_failed_attempts: 2, max_parallel: 1,
|
|
71
|
+
} } };
|
|
72
|
+
if (review !== 'Off') config.blender_subagents.graders = {
|
|
73
|
+
enabled: true, agent: 'blender-grader', max_parallel: 1, max_rounds: 2,
|
|
74
|
+
graders: [{ name: 'visual', focus: 'composition', provider: 'test', model: 'test-model', variant: 'test-variant', backup: { provider: 'backup-test', model: 'backup-test-model', variant: 'backup-test-variant' }, max_steps: 12, max_minutes: 5 }],
|
|
75
|
+
};
|
|
76
|
+
write('.kilo/blender-project-harness/config.json', JSON.stringify(config));
|
|
77
|
+
git(root, ['init', '--quiet']);
|
|
78
|
+
git(root, ['add', '--', '.']);
|
|
79
|
+
const commit = (message = 'test: fixture checkpoint') => git(root, ['-c', 'user.name=Harness Test', '-c', 'user.email=harness-test@example.invalid', 'commit', '--quiet', '-m', message]);
|
|
80
|
+
commit('test: fixture scaffold');
|
|
81
|
+
const harness = new Harness(root, { stateRoot: path.join(temp, 'state') });
|
|
82
|
+
const session = 'ses_orchestrator';
|
|
83
|
+
const questionArgs = (question, labels) => ({ questions: [{ question, custom: false, multiple: false, options: labels.map((label) => ({ label, description: label })) }] });
|
|
84
|
+
const registration = harness.prepare(session, { project, scene: 'scene.blend', goal });
|
|
85
|
+
harness.question(session, questionArgs(registration.question, registration.labels), [['Confirm registration']]);
|
|
86
|
+
const begin = () => {
|
|
87
|
+
harness.command(session, 'goal-active', { objective });
|
|
88
|
+
return harness.command(session, 'begin', { outcome: 'Create fixture composition', objects: ['Cube'], paths: ['notes.txt', 'Documents/DECISIONS.md'], final: true });
|
|
89
|
+
};
|
|
90
|
+
return { root, project, scene, goal, objective, write, commit, harness, session, questionArgs, begin };
|
|
91
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export const INSTALL_RELATIVE = path.join('.kilo', 'blender-project-harness');
|
|
5
|
+
export const CONFIG_RELATIVE = path.join(INSTALL_RELATIVE, 'config.json');
|
|
6
|
+
|
|
7
|
+
export function workspaceRoot(start) {
|
|
8
|
+
const explicit = process.env.BLENDER_WORKSPACE_ROOT;
|
|
9
|
+
if (explicit) {
|
|
10
|
+
const resolved = path.resolve(explicit);
|
|
11
|
+
if (fs.existsSync(resolved)) return resolved;
|
|
12
|
+
}
|
|
13
|
+
let current = path.resolve(start);
|
|
14
|
+
while (true) {
|
|
15
|
+
if (fs.existsSync(path.join(current, '.kilo'))
|
|
16
|
+
&& (fs.existsSync(path.join(current, 'Blender')) || fs.existsSync(path.join(current, 'AGENTS.md')))) {
|
|
17
|
+
return current;
|
|
18
|
+
}
|
|
19
|
+
const parent = path.dirname(current);
|
|
20
|
+
if (parent === current) break;
|
|
21
|
+
current = parent;
|
|
22
|
+
}
|
|
23
|
+
const cwd = path.resolve(process.cwd());
|
|
24
|
+
if (fs.existsSync(path.join(cwd, '.kilo'))) return cwd;
|
|
25
|
+
return path.resolve(start, '..', '..');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function configPath(root) {
|
|
29
|
+
return path.join(root, CONFIG_RELATIVE);
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { configPath, workspaceRoot } from './workspace.mjs';
|
|
7
|
+
|
|
8
|
+
test('workspace root resolves from the installed harness path', (t) => {
|
|
9
|
+
const previous = process.env.BLENDER_WORKSPACE_ROOT;
|
|
10
|
+
delete process.env.BLENDER_WORKSPACE_ROOT;
|
|
11
|
+
t.after(() => {
|
|
12
|
+
if (previous === undefined) delete process.env.BLENDER_WORKSPACE_ROOT;
|
|
13
|
+
else process.env.BLENDER_WORKSPACE_ROOT = previous;
|
|
14
|
+
});
|
|
15
|
+
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'blender-workspace-root-'));
|
|
16
|
+
t.after(() => fs.rmSync(temp, { recursive: true, force: true }));
|
|
17
|
+
const root = path.join(temp, 'workspace');
|
|
18
|
+
fs.mkdirSync(path.join(root, '.kilo'), { recursive: true });
|
|
19
|
+
fs.mkdirSync(path.join(root, 'Blender'), { recursive: true });
|
|
20
|
+
const harness = path.join(root, '.kilo', 'blender-project-harness', 'tools', 'harness');
|
|
21
|
+
fs.mkdirSync(harness, { recursive: true });
|
|
22
|
+
assert.equal(workspaceRoot(harness), root);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('config path is always the installed harness config', (t) => {
|
|
26
|
+
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'blender-workspace-config-'));
|
|
27
|
+
t.after(() => fs.rmSync(temp, { recursive: true, force: true }));
|
|
28
|
+
const root = path.join(temp, 'workspace');
|
|
29
|
+
fs.mkdirSync(root, { recursive: true });
|
|
30
|
+
assert.equal(configPath(root), path.join(root, '.kilo', 'blender-project-harness', 'config.json'));
|
|
31
|
+
});
|