From 8c957d38007b09be362cca3ca5e76fd37ffef709 Mon Sep 17 00:00:00 2001
From: inisho2-byte <271870614+inisho2-byte@users.noreply.github.com>
Date: Wed, 14 Oct 2026 09:22:40 -0500
Subject: [PATCH] Add portable motion analysis and physical 3D toolkit
---
.github/workflows/core.yml | 4 +-
AGENTS.md | 2 +
CHANGELOG.md | 31 +-
Editing_OS/Skills/MASTER_PROMPT.md | 5 +
Editing_OS/Skills/PROVENANCE.md | 26 ++
Editing_OS/Skills/QUALITY_STANDARD.md | 4 +
Editing_OS/Skills/README.md | 11 +
Editing_OS/Skills/SCENE_PATTERNS.md | 4 +
Editing_OS/Skills/SPECIALIST_BOUNDARIES.md | 4 +
Editing_OS/Skills/START_HERE.md | 10 +
Editing_OS/Skills/STYLE_LIBRARY.md | 15 +
Editing_OS/Skills/TASTE_PROFILE.md | 4 +
Editing_OS/Skills/TOOL_ROUTING.md | 10 +
.../Elite_AI_Video_Editing_Workflow.md | 292 +++++++++++++++++
.../audio-reactive-motion/IMPLEMENTATION.md | 142 +++++++++
.../Skills/audio-reactive-motion/SKILL.md | 113 +++++++
.../Skills/motion-graphics-recipes/BROLL.md | 71 +++++
.../motion-graphics-recipes/EXPLAINERS.md | 104 +++++++
.../Skills/motion-graphics-recipes/SKILL.md | 107 +++++++
.../motion-graphics-recipes/SOUND_DESIGN.md | 75 +++++
.../motion-graphics-recipes/SUBJECT_MASKS.md | 65 ++++
.../DEPTH_AND_MOTION.md | 120 +++++++
.../MEDIUM_RECIPES.md | 68 ++++
.../procedural-motion-design/PIPELINE.md | 90 ++++++
.../Skills/procedural-motion-design/SKILL.md | 74 +++++
.../STYLE_IDENTITY.md | 102 ++++++
.../Skills/studio-3d-objects/ADVANCED_3D.md | 140 +++++++++
Editing_OS/Skills/studio-3d-objects/OPS.md | 9 +
Editing_OS/Skills/studio-3d-objects/SKILL.md | 37 +++
.../Skills/studio-3d-objects/SOURCE_MAP.md | 29 ++
.../studio-3d-objects/STYLE_IDENTITY.md | 77 +++++
.../studio-3d-objects/WEB_AND_ASSETS.md | 92 ++++++
.../studio-3d-objects/starter/README.md | 9 +
.../starter/beat-template.html | 18 ++
.../examples/cards-scatter-file-in.html | 18 ++
.../starter/examples/folder-cards-rise.html | 18 ++
.../starter/examples/mat-loupe-stamp.html | 18 ++
.../starter/examples/monitor-timeline.html | 18 ++
.../starter/examples/tablet-over-footage.html | 18 ++
.../studio-3d-objects/starter/stage.css | 17 +
.../studio-3d-objects/starter/studio3d.js | 293 ++++++++++++++++++
Editing_OS/Tools/editing-workbench/GUIDE.md | 4 +
.../Tools/editing-workbench/audio_motion.py | 157 ++++++++++
.../editing-workbench/capability_examples.py | 166 ++++++++++
.../Tools/editing-workbench/style_inspect.py | 163 ++++++++++
.../editing-workbench/test_audio_motion.py | 112 +++++++
.../Tools/editing-workbench/test_studio3d.py | 45 +++
.../editing-workbench/test_style_inspect.py | 107 +++++++
.../production-context.v1.example.json | 10 +-
Editing_OS/runtime_paths.py | 16 +-
LICENSE-SCOPE.md | 2 +
README.md | 3 +-
THIRD_PARTY_NOTICES.md | 6 +
config/candidate-status.json | 46 ++-
config/toolkit.example.json | 4 +-
config/tools.manifest.json | 37 ++-
docs/architecture.md | 11 +
docs/capabilities.md | 14 +-
docs/configuration.md | 9 +
docs/getting-started.md | 13 +-
docs/installation.md | 20 +-
docs/maintenance.md | 2 +-
docs/new-capabilities.md | 56 ++++
docs/optional-tools.md | 11 +
docs/troubleshooting.md | 15 +
docs/verification.md | 61 +++-
docs/workflow.md | 11 +
notices/ACE-Step-MIT.txt | 21 ++
notices/Animate-MIT.txt | 21 ++
notices/Barty-Bart-MIT.txt | 25 ++
requirements-style.lock.txt | 1 +
requirements-style.txt | 2 +
scripts/export_release.py | 7 +-
scripts/run_checks.py | 10 +-
tests/test_exporter.py | 151 +++++++++
tests/test_helper_boundaries.py | 82 +++++
toolkit.json | 2 +-
77 files changed, 3721 insertions(+), 66 deletions(-)
create mode 100644 Editing_OS/Skills/PROVENANCE.md
create mode 100644 Editing_OS/Skills/STYLE_LIBRARY.md
create mode 100644 Editing_OS/Skills/audio-reactive-motion/IMPLEMENTATION.md
create mode 100644 Editing_OS/Skills/audio-reactive-motion/SKILL.md
create mode 100644 Editing_OS/Skills/motion-graphics-recipes/BROLL.md
create mode 100644 Editing_OS/Skills/motion-graphics-recipes/EXPLAINERS.md
create mode 100644 Editing_OS/Skills/motion-graphics-recipes/SKILL.md
create mode 100644 Editing_OS/Skills/motion-graphics-recipes/SOUND_DESIGN.md
create mode 100644 Editing_OS/Skills/motion-graphics-recipes/SUBJECT_MASKS.md
create mode 100644 Editing_OS/Skills/procedural-motion-design/DEPTH_AND_MOTION.md
create mode 100644 Editing_OS/Skills/procedural-motion-design/MEDIUM_RECIPES.md
create mode 100644 Editing_OS/Skills/procedural-motion-design/PIPELINE.md
create mode 100644 Editing_OS/Skills/procedural-motion-design/SKILL.md
create mode 100644 Editing_OS/Skills/procedural-motion-design/STYLE_IDENTITY.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/ADVANCED_3D.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/OPS.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/SKILL.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/SOURCE_MAP.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/STYLE_IDENTITY.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/WEB_AND_ASSETS.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/README.md
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/beat-template.html
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/examples/cards-scatter-file-in.html
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/examples/folder-cards-rise.html
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/examples/mat-loupe-stamp.html
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/examples/monitor-timeline.html
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/examples/tablet-over-footage.html
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/stage.css
create mode 100644 Editing_OS/Skills/studio-3d-objects/starter/studio3d.js
create mode 100644 Editing_OS/Tools/editing-workbench/audio_motion.py
create mode 100644 Editing_OS/Tools/editing-workbench/capability_examples.py
create mode 100644 Editing_OS/Tools/editing-workbench/style_inspect.py
create mode 100644 Editing_OS/Tools/editing-workbench/test_audio_motion.py
create mode 100644 Editing_OS/Tools/editing-workbench/test_studio3d.py
create mode 100644 Editing_OS/Tools/editing-workbench/test_style_inspect.py
create mode 100644 docs/new-capabilities.md
create mode 100644 notices/ACE-Step-MIT.txt
create mode 100644 notices/Animate-MIT.txt
create mode 100644 notices/Barty-Bart-MIT.txt
create mode 100644 requirements-style.lock.txt
create mode 100644 requirements-style.txt
create mode 100644 tests/test_exporter.py
create mode 100644 tests/test_helper_boundaries.py
diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml
index d312890..152f9fc 100644
--- a/.github/workflows/core.yml
+++ b/.github/workflows/core.yml
@@ -25,7 +25,7 @@ jobs:
- name: Install locked core dependencies
shell: pwsh
run: |
- python -m pip install --only-binary=:all: -r requirements-core.lock.txt
+ python -m pip install --only-binary=:all: -r requirements-core.lock.txt -r requirements-style.lock.txt
if ($LASTEXITCODE -ne 0) { throw 'Core install failed' }
python -m pip check
if ($LASTEXITCODE -ne 0) { throw 'Dependency consistency failed' }
@@ -59,7 +59,7 @@ jobs:
shell: pwsh
run: |
$VerifyWorkspace = Join-Path $env:RUNNER_TEMP 'editing-pack-workspace'
- python -B scripts/run_checks.py --workspace $VerifyWorkspace
+ python -B scripts/run_checks.py --workspace $VerifyWorkspace --style-analysis
if ($LASTEXITCODE -ne 0) { throw 'Core checks failed' }
python -B scripts/synthetic_walkthrough.py --workspace $VerifyWorkspace
if ($LASTEXITCODE -ne 0) { throw 'Synthetic walkthrough failed' }
diff --git a/AGENTS.md b/AGENTS.md
index 5306cd3..611d991 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -20,3 +20,5 @@ Use session-owned preview processes; identify an existing server's owner before
For toolkit changes, review exact paths, licenses and privacy before a public push. Private release inventories/scan logs and excluded-project names must stay outside the public repository. Authored public docs are maintained here; no household schema or parent-generated README is exported. Keep governing-document hashes current after changes; never reuse old approvals or weaken gates to pass tests.
Owned operational instructions are MIT. Explanatory docs/handbook are CC BY 4.0, with MIT code snippets, as detailed in LICENSE-SCOPE.md. Third-party terms remain separate. Do not claim native-app, alignment, cross-platform or clean-install support without the corresponding verification.
+
+New specialist routes: audio-reactive-motion, motion-graphics-recipes, procedural-motion-design and studio-3d-objects under Editing_OS/Skills. Load applicable guidance and handbook Chapter23, not every specialist at startup. Existing contracts/genuine approvals remain authoritative. No private filesystem, vendor runtime or approval is bundled.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b3ffa2..94652df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,28 @@
# Changelog
-Unreleased entries describe the local candidate. Proposed initial prerelease: 0.1.0-rc.1. No public tag or publication date is assigned yet.
+## Unreleased — proposed 0.2.0-rc.1
-## 0.1.0-rc.1 — prepared candidate
+- Add four generic specialist families, an unapproved style catalog and original
+ Chapter 23 method routing for 118 studied techniques with explicit limits.
+- Add guarded offline audio analysis, optional Pillow image analysis and an owned
+ physical 3D starter with explicit external Three/browser resources.
+- Add generated-input examples, exporter web-source/privacy regressions and
+ separate core/style/graphics/3D browser test profiles.
+- Preserve existing portable engines, production schema semantics, forced
+ alignment, approved cuts, selected treatment and encoded human-review gates.
+- Correct obsolete first-release preparation wording and document configuration,
+ licenses, prerequisite failures, software rendering cost and capture limits.
-- Prepared inspectable owned source, handbook, operating instructions, production contracts and editing/caption/graphics/quality engines.
-- Added standalone configuration, external workspaces, pinned core setup and opt-in graphics/native SDK dependencies.
-- Preserved timing, explicit treatment and encoded-artifact review gates; labelled synthetic fixtures and conditional integrations.
-- Added onboarding, capability limits, privacy, troubleshooting, contributing, private security reporting and maintenance guidance.
+Exact candidate approval, public CI and independent public-clone verification
+remain required before assigning a new publication date.
-Release notes must describe actual verification, conditional paths and schema/config compatibility changes. See [maintenance](docs/maintenance.md).
+## 0.1.0-rc.1 — 2026-10-11
-- Fresh Windows verification: 184 core/213 optional checks, synthetic and headless browser decode/repeat checks. Live models/native editor work remain unverified.
-- Prepared Windows core/synthetic, dependency consistency, local link/source and checksum-pinned secret scanning CI. GitHub execution remains pending publication.
+- Published owned handbook, operating instructions, production contracts,
+ editing/caption/graphics/quality engines and portable configuration.
+- Verified 184 core and 29 optional graphics checks on Windows, synthetic clock,
+ browser encoding, decode/repeats and authority refusals.
+- Published through the protected PR workflow with CI checks. Optional models,
+ paid providers and native editor execution remained unverified.
+
+See [maintenance](docs/maintenance.md) for version and publication practice.
diff --git a/Editing_OS/Skills/MASTER_PROMPT.md b/Editing_OS/Skills/MASTER_PROMPT.md
index 8d9b4e7..612c8fd 100644
--- a/Editing_OS/Skills/MASTER_PROMPT.md
+++ b/Editing_OS/Skills/MASTER_PROMPT.md
@@ -193,3 +193,8 @@ Begin only once the source material (transcript, footage notes, platform, goal)
and active contracts are available and `production-context/v1` validates. If
they are not, ask for them or create the missing context before execution.
```
+
+SPECIALIST EXTENSIONS
+- Load only the applicable new recipe: audio-reactive-motion, motion-graphics-recipes, procedural-motion-design or studio-3d-objects. Use Chapter23 for studied methods and their limits. Neither a genre nor an upstream skill selects treatment.
+- Native3D/object scenes require explicit local assets, failed-dependency rejection, seek-safe state and applicable full-size/encoded/repeat evidence. Model/website/native-editor paths remain conditional until separately verified.
+- Keep reusable code in the toolkit and all actual jobs/evidence in the selected external workspace. Keep production schema roles/capabilities unchanged; recipe names are not new enums.
diff --git a/Editing_OS/Skills/PROVENANCE.md b/Editing_OS/Skills/PROVENANCE.md
new file mode 100644
index 0000000..c44cbcd
--- /dev/null
+++ b/Editing_OS/Skills/PROVENANCE.md
@@ -0,0 +1,26 @@
+# Public source and method provenance
+
+The four recipe families and handbook methods are owned, original adaptations. References are study provenance, not downloaded runtimes, source assets, malware audits or implementation certificates. No private study report, transcript, case history or human decision is included.
+
+| Reference | Inspected revision | Distribution boundary |
+|---|---|---|
+| [mrdoob/three.js](https://github.com/mrdoob/three.js/tree/286e2d8cba7088982eb9068d4bb8f68e42c3bf67) | 286e2d8cba7088982eb9068d4bb8f68e42c3bf67 | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [CloudAI-X/threejs-skills](https://github.com/CloudAI-X/threejs-skills/tree/b1c623076c661fc9b03dac19292e825a5d106823) | b1c623076c661fc9b03dac19292e825a5d106823 | Citation only; no verified redistribution license, no upstream code/prose/assets copied |
+| [majidmanzarpour/threejs-game-skills](https://github.com/majidmanzarpour/threejs-game-skills/tree/8286774b22a2566bf894dbc825825c16921866af) | 8286774b22a2566bf894dbc825825c16921866af | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [nextlevelbuilder/ui-ux-pro-max-skill](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/tree/7246805992a42b7bba37d4cac83b01416f0c6c44) | 7246805992a42b7bba37d4cac83b01416f0c6c44 | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [pmndrs/react-three-fiber](https://github.com/pmndrs/react-three-fiber/tree/a9f8dc052b2c80788b3d3464d1e9eaf79b12a600) | a9f8dc052b2c80788b3d3464d1e9eaf79b12a600 | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [pmndrs/drei](https://github.com/pmndrs/drei/tree/bf6f4addf47467d3885de272d94ca5127f6ef68f) | bf6f4addf47467d3885de272d94ca5127f6ef68f | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [donmccurdy/glTF-Transform](https://github.com/donmccurdy/glTF-Transform/tree/3797aad585021e68cf5fbf3f2fba37783596ffac) | 3797aad585021e68cf5fbf3f2fba37783596ffac | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [shadcn-ui/ui](https://github.com/shadcn-ui/ui/tree/30a58d4498f270af1c1e981a7d78a15cf5740841) | 30a58d4498f270af1c1e981a7d78a15cf5740841 | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [theatre-js/theatre](https://github.com/theatre-js/theatre/tree/6ea82b938ea49609489f6377ded693ccc6ee8f5b) | 6ea82b938ea49609489f6377ded693ccc6ee8f5b | Original method guidance; upstream code/assets not bundled; external components retain Apache-2.0 terms |
+| [ACE-Step/ACE-Step-1.5](https://github.com/ACE-Step/ACE-Step-1.5/tree/ca1e85fe9430179831e6bc6be790c332190a3866) | ca1e85fe9430179831e6bc6be790c332190a3866 | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+| [Barty-Bart/motion-graphics](https://github.com/Barty-Bart/motion-graphics/tree/3d83d987d658601d8a1269eb691622bdcd427335) | 3d83d987d658601d8a1269eb691622bdcd427335 | Original method guidance; upstream code/assets not bundled; external components retain MIT (root text verified; font/icon terms separate) terms |
+| [cth9191/animate](https://github.com/cth9191/animate/tree/7e5eb56feb2dd573f890e1b7b34748af43d58263) | 7e5eb56feb2dd573f890e1b7b34748af43d58263 | Original method guidance; upstream code/assets not bundled; external components retain MIT terms |
+
+## Runtime resources
+
+Explicit external packages: Three.js0.185.0 (MIT), GSAP3.15.0 (custom Standard License), Inter5.2.8 (OFL1.1), Puppeteer-core25.13.0 (Apache2.0) and HyperFrames0.8.146 (Apache2.0). Pillow12.3.0 (MIT-CMU and separately licensed bundled components) is optional for bounded still-image observations. The source release contains no installed libraries/fonts/browser/model files. Generated external sites retain runtime/font notices and resource SHA256 values. Read actual installed package terms before additional runtimes or assets are used.
+
+Theatre sources/editor packages may have separate terms; no Theatre runtime is shipped. Geist fonts/Lucide icons from the motion source are excluded. CloudAI-X source remains excluded. Tutorial URLs in handbook Chapter23 identify public study material; the handbook provides original concise methods, not exported tutorial transcripts/media.118 rows are indexed studied topics with verification limits, not118 implemented techniques.
+
+Production uses the existing genuine timing/taste/evidence/Quality/human-review gates.
diff --git a/Editing_OS/Skills/QUALITY_STANDARD.md b/Editing_OS/Skills/QUALITY_STANDARD.md
index a73b1ac..2cd1fd1 100644
--- a/Editing_OS/Skills/QUALITY_STANDARD.md
+++ b/Editing_OS/Skills/QUALITY_STANDARD.md
@@ -433,3 +433,7 @@ python -B -m unittest -v test_quality_engine.py
Then run the quality engine against the final artifact and a second independent
render. A test suite that passes without examining the actual delivery file is
necessary but insufficient.
+
+## Bespoke runtime and studied-method scope
+
+A required3D profile fails on missing resources, readiness rejection, blank canvas, wrong host offsets or broken random/forward/backward seeks. Shared/caller disposal remains distinct. Check glyphs, silhouettes, transmission/material effects and actual full-size frames. Preserve backend/cost and hardware repeat failures; verify independent decoded software repeats where claimed. Style/audio diagnostics and the118-technique study register are not realized production evidence. Use existing graphics/audio/caption evidence plus full encoded Quality and exact-hash human review; never add a fabricated waiver or approval to satisfy a gate.
diff --git a/Editing_OS/Skills/README.md b/Editing_OS/Skills/README.md
index fb152e6..0f2e60a 100644
--- a/Editing_OS/Skills/README.md
+++ b/Editing_OS/Skills/README.md
@@ -5,3 +5,14 @@ Start at [START_HERE](START_HERE.md). Load [master prompt](MASTER_PROMPT.md), [t
[Scene patterns](SCENE_PATTERNS.md) support planning; [specialist boundaries](SPECIALIST_BOUNDARIES.md) explain tools; [claim register](Evidence/CLAIM_REGISTER.md) qualifies heuristics. Examples are not real alignment/approval.
New users start at [getting started](../../docs/getting-started.md). Operational instructions are MIT; explanatory READMEs/handbook are CC BY 4.0 with MIT snippets under [license scope](../../LICENSE-SCOPE.md).
+
+| Task | Load when applicable | Implemented scope |
+|---|---|---|
+| Music-driven motion | [Audio reactive motion](audio-reactive-motion/SKILL.md) | Offline PCM analysis; no music model or automatic taste approval |
+| B-roll, mattes, sound passes | [Motion recipes](motion-graphics-recipes/SKILL.md) | Craft guidance; segmentation and assets require verified external capability |
+| Reference identity and medium | [Procedural motion](procedural-motion-design/SKILL.md) | Bounded image observations and design guidance; no installed Animate runtime |
+| Physical 3D objects | [Studio 3D](studio-3d-objects/SKILL.md) | Owned Three.js starter; explicit external resources and browser profile |
+
+See [generated-input examples](../../docs/new-capabilities.md), the generic
+[style catalog](STYLE_LIBRARY.md) and [provenance](PROVENANCE.md). Studied sources,
+example recipes and successful tests do not approve a real production treatment.
diff --git a/Editing_OS/Skills/SCENE_PATTERNS.md b/Editing_OS/Skills/SCENE_PATTERNS.md
index 0bdd9c9..020870b 100644
--- a/Editing_OS/Skills/SCENE_PATTERNS.md
+++ b/Editing_OS/Skills/SCENE_PATTERNS.md
@@ -57,3 +57,7 @@ before animation. Do not imply rights from a filename or a successful download.
Check motion in reading order, captions against actual speech, audio/listening
continuity at every cut, and consistency between grade/background/type. Historical
project colors, typography sizes and PiP coordinates remain project-specific.
+
+## New specialist recipes
+
+Use [motion recipes](motion-graphics-recipes/SKILL.md) for persistent-object workflow and product explanations, [audio response](audio-reactive-motion/SKILL.md) for measured music accents, and [procedural identity](procedural-motion-design/SKILL.md) for a coherent reference vocabulary. [Studio objects](studio-3d-objects/SKILL.md) supplies real object actions; illustrative geometry is distinct from source proof. Preserve trigger, settling hold, meaningful final state, source/output clock and explicit selected treatment. No recipe overrides existing schemas/gates.
diff --git a/Editing_OS/Skills/SPECIALIST_BOUNDARIES.md b/Editing_OS/Skills/SPECIALIST_BOUNDARIES.md
index d66e344..4fae1f7 100644
--- a/Editing_OS/Skills/SPECIALIST_BOUNDARIES.md
+++ b/Editing_OS/Skills/SPECIALIST_BOUNDARIES.md
@@ -35,3 +35,7 @@ The nested Video editing engine's authored README still describes direct
`--apply-edits` as approval. That is historical diagnostic behavior. Current
production must use the owned Orchestration Adapter and consume its exact
authorization; no submodule internals were changed by this upgrade.
+
+## New method references
+
+Upstream drawing/window.seek/playback conventions, live audio analyzers, website controls, vendor scores and studied technique counts do not replace the native HyperFrames output clock, current forced alignment/retiming, explicit human taste or encoded readiness. No ACE-Step, Barty, Animate, Fiber/Drei/Theatre/shadcn runtime, optimizer or model is installed by these recipes. External resources are deliberately provisioned and license-checked.
diff --git a/Editing_OS/Skills/START_HERE.md b/Editing_OS/Skills/START_HERE.md
index 7a16e50..af229ec 100644
--- a/Editing_OS/Skills/START_HERE.md
+++ b/Editing_OS/Skills/START_HERE.md
@@ -13,3 +13,13 @@ For first-time setup, follow [getting started](../../docs/getting-started.md). F
The owned workbench is at Editing_OS/Tools/editing-workbench; from this file use [its guide](../Tools/editing-workbench/GUIDE.md). Scene guidance is in [SCENE_PATTERNS.md](SCENE_PATTERNS.md). Use [installation](../../docs/installation.md) and [configuration](../../docs/configuration.md) for the tested standalone Windows setup. Example approvals never authorize a real job.
See [architecture](../../docs/architecture.md), [workflow](../../docs/workflow.md) and [capabilities](../../docs/capabilities.md) for public entry points and limits.
+
+## Additional specialist navigation
+
+- [Audio reaction](audio-reactive-motion/SKILL.md): standard-library PCM analysis and verified lyric/timing boundaries.
+- [Motion recipes](motion-graphics-recipes/SKILL.md): B-roll, product/process explanation, matte handoffs and sound passes.
+- [Procedural/reference identity](procedural-motion-design/SKILL.md): seven vocabularies, optional bounded Pillow observations, explicit treatment.
+- [Studio objects](studio-3d-objects/SKILL.md): local3D starter, required browser regression and generic draft scenes.
+- [Generic styles](STYLE_LIBRARY.md) and [public provenance](PROVENANCE.md): unapproved examples and external source scope.
+
+Run workbench capability_examples with an explicit external workspace/config and draft flag; production uses the existing authority path, not example decisions.
diff --git a/Editing_OS/Skills/STYLE_LIBRARY.md b/Editing_OS/Skills/STYLE_LIBRARY.md
new file mode 100644
index 0000000..39180fe
--- /dev/null
+++ b/Editing_OS/Skills/STYLE_LIBRARY.md
@@ -0,0 +1,15 @@
+# Generic style catalog
+
+All entries are unapproved starting points. A catalog label never selects a production treatment. Use the actual content/reference, show options where unresolved, and record the human decision in taste-selection/v1. Do not copy a style's example status into approval evidence.
+
+| Example family | Adjustable properties | Scope |
+|---|---|---|
+| Clear editorial | Type hierarchy, whitespace, semantic reveals and stable captions | Proposed design vocabulary |
+| Paper and printed matter | Surface grain, registration, physical folds and constrained light | Procedural illustration or verified local 3D |
+| Studio objects | Geometry, hinge phases, material, camera and contact shadows | Owned Three.js draft starter, external runtime required |
+| Audio response | FFT bands, attack/release, peak clearance and actual placed-audio clock | Measured reaction, not beat/lyric alignment |
+| Reference-derived identity | Shape, relative palette, light, typography and motion cadence | Original observations; no automatic resemblance claim |
+
+A job style record contains source/rights/hash, observed identity rules, proposed tokens, requested variants, explicit selection evidence and verification limits. Keep real references, screenshots, human decisions and job records in the external workspace. Promote no draft catalog entry into an approved style without genuine selection.
+
+See [procedural identity](procedural-motion-design/STYLE_IDENTITY.md), [studio identity](studio-3d-objects/STYLE_IDENTITY.md) and [source notes](PROVENANCE.md).
diff --git a/Editing_OS/Skills/TASTE_PROFILE.md b/Editing_OS/Skills/TASTE_PROFILE.md
index c80f9c8..a617ffc 100644
--- a/Editing_OS/Skills/TASTE_PROFILE.md
+++ b/Editing_OS/Skills/TASTE_PROFILE.md
@@ -19,3 +19,7 @@ Favor a clear hierarchy and adequate reading time while evaluating alternatives;
## Preserve evidence
Hash the current governing template with the other four documents when creating production context. Store the private selected treatment and its artifacts in the job workspace. Any local edit to this governing document changes its hash and requires a new context and revalidation of dependent authority. No history from another user or project is inherited.
+
+## Reference and3D treatment choices
+
+The generic STYLE_LIBRARY and starter materials are unapproved examples. Compare shape, light, camera, materials, typography and motion against the actual reference/content. When unresolved, show useful options on the same material and freeze the explicit choice. Select capture mode deliberately; a renderer/backend label is not a visual or determinism pass. Never publish personal style history as reusable defaults.
diff --git a/Editing_OS/Skills/TOOL_ROUTING.md b/Editing_OS/Skills/TOOL_ROUTING.md
index da93e63..bb1554f 100644
--- a/Editing_OS/Skills/TOOL_ROUTING.md
+++ b/Editing_OS/Skills/TOOL_ROUTING.md
@@ -127,3 +127,13 @@ authoritative specialist path; and the Quality Engine alone may issue
## Standalone tools and handoffs
Owned workbench utilities live at Editing_OS/Tools/editing-workbench. External specialists remain outside this repository and use config/tools.manifest.json pins and their own terms. Use docs/installation.md and docs/configuration.md for explicit external paths and tested package versions; existing machine/browser paths and historical render speeds are not public prerequisites. GSAP and Inter resources require explicit licensed provisioning. Native bridges are conditional prototypes; the adapter and Quality Engine remain the authority.
+
+## Additional owned routes
+
+| Need | Owner | Limit |
+|---|---|---|
+| Measured PCM reaction | [audio-reactive-motion](audio-reactive-motion/SKILL.md), public audio_motion helper | Energy is not beat/word alignment |
+| Product/motion B-roll, mattes and sound passes | [motion-graphics-recipes](motion-graphics-recipes/SKILL.md) | Existing semantic/taste/runtime/evidence owners remain authoritative |
+| Reference/medium observations | [procedural-motion-design](procedural-motion-design/SKILL.md), optional style_inspect helper | Pillow observations do not infer style similarity or approval |
+| Physical object scene | [studio-3d-objects](studio-3d-objects/SKILL.md) | Explicit local Three/GSAP/fonts/browser; software/hardware evidence is scoped |
+| Model animation/optimization or website scene | Applicable3D/web guidance | Conditional tools; nine studied references are not nine installed integrations |
diff --git a/Editing_OS/Skills/Video editing handbook/Elite_AI_Video_Editing_Workflow.md b/Editing_OS/Skills/Video editing handbook/Elite_AI_Video_Editing_Workflow.md
index 54ce2e2..70d21c2 100644
--- a/Editing_OS/Skills/Video editing handbook/Elite_AI_Video_Editing_Workflow.md
+++ b/Editing_OS/Skills/Video editing handbook/Elite_AI_Video_Editing_Workflow.md
@@ -9258,3 +9258,295 @@ Remember:
> **You have built an editor, not learned a tool. The tools will change many times before the craft changes once — and now they are on their own page, where their changing can never touch the part that matters.**
---
+
+
+# Chapter 23 — Methods, source scope and verification limits
+
+This chapter provides original reusable method guidance informed by a studied public editing tutorial. The register retains118 studied technique IDs for traceability; they are not118 implemented engines, completed native actions or statistical quality guarantees. Tutorial project assets, transcripts, private study reports and empirical job observations are excluded.
+
+Public study references: [editing tutorial](https://www.youtube.com/watch?v=O6ERELse_QY) and [context reference](https://www.youtube.com/watch?v=qthiuEt_moU). These links establish provenance, not source rights or production readiness.
+
+
+## R01 — Inspect real material and distinguish clocks
+
+Inspect playback and individual frames, then distinguish source timestamps, editor time and output time. Check the actual retained boundary and decode; a requested seek does not prove the selected source frame.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R02 — Automate known state and preserve bindings
+
+Automate only an understood application state. Preserve bindings and user preferences, expose selected targets and read back changes rather than treating a macro completion as proof.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R03 — Trace inputs, versions and missing coverage
+
+Record input identity, version, rights and missing coverage. Link review evidence to the exact source bytes; absent footage and an unreviewed file are different gaps.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R04 — Recover known-good work without overwriting it
+
+Keep a known-good version recoverable. Work in an isolated copy with explicit provenance; a new edit must not silently overwrite either the source or an approved output.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R05 — Choose audio channels and processing scope deliberately
+
+Choose channel and track processing scope deliberately. Associated source sound may convey meaning; track processing does not replace individual clip or message review.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R06 — Keep gain and loudness units distinct
+
+Distinguish sample peak, clip gain, true peak and loudness. Record units and actual processing context, then measure the encoded result; no inherited limiter value is a universal default.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R07 — Protect message-bearing sound and motivate effects
+
+Keep message-bearing speech/sound intelligible and use effects for a specific action or meaning. Frequency/energy detection is diagnostic evidence, not proof that a whoosh or musical hit fits.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R08 — Correct the relevant problem and keep source limits visible
+
+Correct the relevant exposure, color, sound or crop problem while preserving source limits. A LUT or overshoot-and-return exercise must not conceal clipped or absent information.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R09 — Separate sound and picture boundaries intentionally
+
+Choose picture and sound boundaries intentionally. J/L cuts use declared placement and reviewable continuity; source and output timing mappings stay explicit.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R10 — Separate assembly from fine timing and protect retained content
+
+Separate assembly from fine timing. Inspect retained speech/actions, protected tracks and marker behavior before ripple edits or automated trimming.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R11 — Judge attribution, comic beats and rescue cost
+
+Evaluate attribution, setup/payoff and the cost of a constructed joke. Do not fabricate evidence or retain a failed shot merely because much effort went into it.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R12 — Fit coverage to spoken order without falsifying evidence
+
+Match coverage to the order of explanation. Allow lead-in and settled recognition time without inventing a causal sequence that the source does not show.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R13 — Retiming preserves a declared story and sound mapping
+
+Declare constant/variable retiming and sound treatment. Recompute output words after approved cuts and review altered actions; acceleration cannot impersonate measured performance.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R14 — Motion directs attention through an intentional path
+
+Choose motion to direct attention along an intentional path. Verify anticipation, intermediate poses, curve direction, contact and readable final holds, not only endpoint screenshots.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R15 — Transitions act on the intended composite
+
+Apply a transition to the intended composite. Check every contributing layer and the midpoint; a decorative movement is not proof of spatial or narrative continuity.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R16 — Preserve real raster detail and deliberate substitutions
+
+Preserve usable raster detail. Inspect the native crop and deliberate replacement asset rather than stretching pixels or inventing a detail that the source cannot support.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R17 — Composites keep labels, grouping and coordinates coherent
+
+Keep labels, masks, grouping and coordinate transforms coherent. Verify the visible composite while distinguishing native tracking internals from manual frame-by-frame adjustments.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R18 — Proof and information density control visual priority
+
+Prioritize the actual claim and control simultaneous information. Make proof readable and attributable; aesthetic complexity must not hide the viewer task.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R19 — Diagnose boundedly and preserve failed experiments
+
+Test a specific suspected failure with bounded controls. Preserve negative results, intermediate states, performance cost and unknowns; tool output cannot erase contradictory evidence.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R20 — Finish and review every actual delivery variant
+
+Finish each real delivery variant and watch its exact encode. A transcode creates new bytes and needs new decode, technical and hash-bound human review evidence.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R21 — Optimize an understood workflow in context
+
+Optimize an understood workflow in context. Navigation shortcuts, supported app APIs and resource budgets must preserve meaning and current project compatibility.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+
+## R22 — Opening and ending shots answer the viewer task
+
+Choose opening and closing shots by the promise and resolution they give the viewer. Inspect attention across cuts and confirm the intended point actually lands.
+
+Verify on actual material through the existing intent, timing/treatment, evidence and encoded-review owners. Native application operations remain conditional on installed supported APIs and independent readback.
+
+## Technique register
+
+P=principle, O=operation, S=application shortcut, E=effect. A partial suffix retains a study limitation. Every row is a studied topic routed to a method; no row certifies implementation.
+
+| ID | Studied topic | Kind | Method | Prerequisites |
+|---|---|---|---|---|
+| T001 | Inspect reference playback and frame-step | O | [R01](#method-R01) | None |
+| T002 | Automate explicit application state | P | [R02](#method-R02) | T001 |
+| T003 | Confirm approved input identity and version | P | [R03](#method-R03) | None |
+| T004 | Maintain an editor working script with comments | O | [R03](#method-R03) | T003 |
+| T005 | Reuse and refresh project templates | O | [R04](#method-R04) | T003 |
+| T006 | Select and route recorded audio channels | O | [R05](#method-R05) | None |
+| T007 | Apply shared track processing and preserve its limitations | O | [R05](#method-R05) | T006 |
+| T008 | Adjust clip gain with units and example context | O | [R06](#method-R06) | T006 |
+| T009 | Apply source-level color and set-specific LUT treatment | O | [R08](#method-R08) | T003 |
+| T010 | Find and apply a named effect preset | S | [R02](#method-R02) | T002 |
+| T011 | Place the playhead from a contextual pointer action | S | [R02](#method-R02) | T002 |
+| T012 | Switch to the intended application window | S | [R02](#method-R02) | T002 |
+| T013 | Separate structural assembly from fine timing | P | [R10](#method-R10) | T003 |
+| T014 | Ripple-remove an unwanted span while protecting retained content | O | [R10](#method-R10) | T013 |
+| T015 | Compare alternate takes with waveform navigation and content checks | O | [R10](#method-R10) | T013 |
+| T016 | Check the slate and unusual source notes | O | [R03](#method-R03) | T003 |
+| T017 | Expose uncertain versus selected decisions | P | [R10](#method-R10) | T003 |
+| T018 | Protect the A-roll base with track locks | O | [R10](#method-R10) | T014 |
+| T019 | Resolve script, footage, and archive references | O | [R03](#method-R03) | T003 |
+| T020 | Fit images while preserving usable native detail | O | [R16](#method-R16) | None |
+| T021 | Adjust correction while recognizing source limits | O | [R08](#method-R08) | T020 |
+| T022 | Retain useful associated source sound | P | [R07](#method-R07) | T006 |
+| T023 | Clarify ambiguous shot intent with its author | P | [R12](#method-R12) | T003 |
+| T024 | Mark useful moments and select source In and Out | O | [R01](#method-R01) | T001 |
+| T025 | Slide a shot to adjust placement | O | [R10](#method-R10) | T018, T024 |
+| T026 | Fit footage to duration through rate adjustment | O | [R13](#method-R13) | T024 |
+| T027 | Assemble an in-camera light reveal with a readable final hold | E | [R13](#method-R13) | T018, T024, T025, T026 |
+| T028 | Introduce incoming audio before its picture: J cut | O | [R09](#method-R09) | T006, T013 |
+| T029 | Carry outgoing audio over the next picture: L cut | O | [R09](#method-R09) | T028 |
+| T030 | Animate picture position and scale for an editorial purpose | O | [R14](#method-R14) | T020 |
+| T031 | Shape a gradual motion start through interpolation | O | [R14](#method-R14) | T030 |
+| T032 | Remove unintended reverse movement in the curve | O | [R14](#method-R14) | T031 |
+| T033 | Lead attention across the cut: eye trace | P | [R14](#method-R14) | T030 |
+| T034 | Label source families and decision states | O | [R03](#method-R03) | T003 |
+| T035 | Protect concentration and take purposeful breaks | P | [R21](#method-R21) | None |
+| T036 | Match multi-action coverage to spoken order | P | [R12](#method-R12) | T013, T024, T026 |
+| T037 | Separate source patching, targeting, and insertion state | O | [R02](#method-R02) | T002, T018 |
+| T038 | Recover matching source audio for a timeline shot | O | [R05](#method-R05) | T022, T037 |
+| T039 | Search and insert a routed SFX asset using a macro | S | [R02](#method-R02) | T002, T037 |
+| T040 | Build a censor-beep treatment | E | [R07](#method-R07) | T008, T024 |
+| T041 | Inspect finer audio units and shape clip edges | O | [R07](#method-R07) | T040 |
+| T042 | Track missing footage and unresolved author questions | O | [R03](#method-R03) | T017, T023 |
+| T043 | Test whether constructed joke attribution and payoff read convincingly | P | [R11](#method-R11) | T013, T036 |
+| T044 | Bind label commands for faster organization | S | [R02](#method-R02) | T002, T034 |
+| T045 | Prioritize intelligible dialogue over competing sound | P | [R07](#method-R07) | T006, T008 |
+| T046 | Decide when stillness or motion supports the edit | P | [R14](#method-R14) | T030, T045 |
+| T047 | Save a supported transition's custom settings | O | [R15](#method-R15) | T010 |
+| T048 | Choose a motion-based handoff while distinguishing spatial continuity | P | [R15](#method-R15) | T030, T033 |
+| T049 | Recover a recent known-working saved version | O | [R04](#method-R04) | T003 |
+| T050 | Span picture layers with an adjustment-layer transition | E | [R15](#method-R15) | T030, T047 |
+| T051 | Avoid uninformative literal B-roll while preserving intentional humor | P | [R12](#method-R12) | T013 |
+| T052 | Find genuinely useful image detail and provenance | O | [R16](#method-R16) | T019, T020 |
+| T053 | Disable an alternative without deleting it | O | [R10](#method-R10) | T013 |
+| T054 | Audition and trim a short music or SFX hit | O | [R07](#method-R07) | T008, T024, T045 |
+| T055 | Arrange clip lanes to expose chronology | O | [R10](#method-R10) | T034 |
+| T056 | Reject a shot despite sunk effort: kill your darlings | P | [R11](#method-R11) | T013, T051 |
+| T057 | Plan script-led coverage, lead-in, holds, and reaction | P | [R12](#method-R12) | T023, T036 |
+| T058 | Save recoverable versions and configure contextual autosave | O | [R04](#method-R04) | T003, T049 |
+| T059 | Verify graph and product assumptions against evidence | P | [R18](#method-R18) | T003, T042 |
+| T060 | Compress waiting without misrepresenting measured performance | P | [R12](#method-R12) | T026, T059 |
+| T061 | Use comparative recordings as supporting evidence | O | [R07](#method-R07) | T008, T019, T022 |
+| T062 | Reuse clean archived shots with identity labels | O | [R03](#method-R03) | T019, T059 |
+| T063 | Capture reproducible bugs and interface context | O | [R19](#method-R19) | T002 |
+| T064 | Accelerate navigation without changing edit timing | S | [R02](#method-R02) | T002 |
+| T065 | Prepare large layered image variants for a deep-zoom joke | E-partial | [R16](#method-R16) | T020, T052 |
+| T066 | Locate, reset, and scrub an effect-panel value | S | [R02](#method-R02) | T002, T030 |
+| T067 | Reuse matching motion while replacing the image asset | E | [R16](#method-R16) | T030, T065 |
+| T068 | Diagnose preview slowdown with bounded tests | O | [R19](#method-R19) | T063 |
+| T069 | Keep sequence, preview, and export geometry explicit | P | [R20](#method-R20) | T020 |
+| T070 | Nest related layers for shared manipulation | O | [R17](#method-R17) | T030, T069 |
+| T071 | Assemble thermal comparison images and readable labels | E-partial | [R17](#method-R17) | T020, T059, T065 |
+| T072 | Overshoot a color adjustment and dial it back | O | [R08](#method-R08) | T021 |
+| T073 | Label product variants and inspect typography and kerning | O | [R17](#method-R17) | T034, T059 |
+| T074 | Try varying clip speed through time remapping | O | [R13](#method-R13) | T026, T030 |
+| T075 | Allocate constrained timing around a comic payoff | P | [R11](#method-R11) | T036, T043, T056, T057 |
+| T076 | Search and audition music for a suitable ending | O | [R07](#method-R07) | T045, T054 |
+| T077 | Audit repeated editing habits and wasted effort | P | [R21](#method-R21) | T056 |
+| T078 | Control simultaneous information and highlight the actual claim | P | [R18](#method-R18) | T033, T059 |
+| T079 | Plan visual choices with output compression in mind | P | [R20](#method-R20) | T069 |
+| T080 | Capture a readable and attributable webpage region | O | [R03](#method-R03) | T020, T052 |
+| T081 | Choose opening and ending shots by intended focal point | P | [R22](#method-R22) | T033, T051 |
+| T082 | Identify schedule buffers and upstream bottlenecks | P | [R21](#method-R21) | T003, T042 |
+| T083 | Adjust music level over time | O | [R07](#method-R07) | T008, T045, T076 |
+| T084 | Track comparison labels to moving footage and recenter picture | E-partial | [R17](#method-R17) | T030, T059, T073 |
+| T085 | Choose a whoosh whose implied motion fits the picture | P | [R07](#method-R07) | T030, T045, T054 |
+| T086 | Capture and freeze a clean data-display frame | O | [R17](#method-R17) | T024, T059, T080 |
+| T087 | Choose software by demonstrated workflow fit | P | [R21](#method-R21) | T077 |
+| T088 | Optimize an understood workflow while preserving its intended result | P | [R21](#method-R21) | T002, T077 |
+| T089 | Reuse supported rendered material and distinguish export mechanisms | O | [R20](#method-R20) | T069 |
+| T090 | Watch the actual encoded output after changes | O | [R20](#method-R20) | T069, T089 |
+| T091 | Hand the identified render to a transcode workflow | S | [R20](#method-R20) | T003, T090 |
+| T092 | Apply a localized masked screen correction | E-partial | [R08](#method-R08) | T009, T021, T030 |
+| T093 | Preserve declared parity between delivery variants | P | [R20](#method-R20) | T003, T090, T092 |
+| T094 | Obtain responsible author and editor review | P | [R20](#method-R20) | T042, T059 |
+| T095 | Separate assembly assistance from creative editing | P | [R10](#method-R10) | T013, T024, T036 |
+| T096 | Preserve settings before resetting preferences | O | [R04](#method-R04) | T003, T058 |
+| T097 | Interpret default-duration units and intermediate settings correctly | O | [R21](#method-R21) | T024, T069 |
+| T098 | Use shuttle monitoring with explicit pitch-preservation context | O | [R01](#method-R01) | T001, T006 |
+| T099 | Inspect through edits and duplicate-frame indicators | O | [R01](#method-R01) | T013, T024 |
+| T100 | Ripple sequence markers with the intended content | O | [R10](#method-R10) | T014, T024 |
+| T101 | Separate undo-history capacity from autosave recovery | O | [R04](#method-R04) | T049, T058 |
+| T102 | Expose useful panel controls and operational state | O | [R02](#method-R02) | T002, T037 |
+| T103 | Choose a contextual missing-media relink route | O | [R03](#method-R03) | T003, T019 |
+| T104 | Cluster, inspect, and preserve shortcut bindings and profiles | S | [R02](#method-R02) | T002, T012, T014 |
+| T105 | Protect active work from untested software upgrades | P | [R04](#method-R04) | T058, T063 |
+| T106 | Reconsider expert advice in its actual context | P | [R21](#method-R21) | T059 |
+| T107 | Explore unfamiliar interface features after foundations | O | [R21](#method-R21) | T001, T102 |
+| T108 | Distinguish correction from grading and aesthetic suitability | P | [R08](#method-R08) | T009, T021 |
+| T109 | Evaluate reversed footage and reattached transitions | O | [R13](#method-R13) | T026, T047, T048 |
+| T110 | Adjust a shared boundary with a rolling edit | O | [R10](#method-R10) | T013, T025 |
+| T111 | Ripple-trim a boundary while preserving protected tracks and markers | O | [R10](#method-R10) | T014, T018 |
+| T112 | Slip source content inside a placed clip and inspect its constraints | O-partial | [R10](#method-R10) | T024, T099 |
+| T113 | Choose a clean frame to hold while an obstruction is absent | O-partial | [R17](#method-R17) | T086 |
+| T114 | Compare track-forward movement with marker-preserving ripple movement | O-partial | [R10](#method-R10) | T100 |
+| T115 | Add an edit across tracks and remove the intended remainder | O | [R10](#method-R10) | T018, T024 |
+| T116 | Time-box feature exploration and record an unsuccessful experiment | P | [R19](#method-R19) | None |
+| T117 | Find the latest saved file of a specified type through a macro | S-partial | [R02](#method-R02) | T003, T049 |
+| T118 | Open a known archive folder directly through a contextual shortcut | S | [R02](#method-R02) | T002, T019 |
+
+## Production boundary
+
+Use existing contracts and capability semantics. Speech requires genuine forced alignment, approved/hash-bound EDL and post-cut retimed words. Subjective treatment requires an explicit genuine selection. Bespoke3D/audio/matte scenes need actual applicable runtime/graphics/caption/audio evidence, exact encoded checks and hash-bound human review. A source score, helper observation, studied method, matching synthetic repeat or integration count supplies none of those approvals.
+
+Retain source clock/decode uncertainty, unavailable proof, failed perceptual controls and unfinished native effects. Match each validation to its claim: a frame does not prove motion, a unit test does not prove a full-size encode and historical hardware throughput does not prove determinism.
diff --git a/Editing_OS/Skills/audio-reactive-motion/IMPLEMENTATION.md b/Editing_OS/Skills/audio-reactive-motion/IMPLEMENTATION.md
new file mode 100644
index 0000000..ba4b91c
--- /dev/null
+++ b/Editing_OS/Skills/audio-reactive-motion/IMPLEMENTATION.md
@@ -0,0 +1,142 @@
+# Audio analysis and choreography recipes
+
+These recipes supply the mechanics for [SKILL.md](); they do not grant
+render approval. Use the existing local HyperFrames core/CLI/animation skills
+at authoring time and inspect its installed API/help. Discover a suitable
+registry visual before building a named effect; reuse only compatible local
+assets. No installation is implied by a missing registry item.
+
+## Offline analysis
+
+The owned helper is Editing-Pack
+[`Editing_OS/Tools/editing-workbench/audio_motion.py`](<../../Tools/editing-workbench/audio_motion.py>).
+It uses only Python's standard library. Run from the toolkit root:
+
+```powershell
+../editing-pack-env/Scripts/python.exe -B Editing_OS/Tools/editing-workbench/audio_motion.py --config config/toolkit.local.json 'path/to/job/analysis.wav' --out 'path/to/job/audio-motion.json' --fps 30000/1001 --bands 24
+```
+
+The source must be an uncompressed signed 16-bit PCM WAV, 8–192 kHz, 1–8
+channels. Use a verified local FFmpeg executable to create a **disposable
+analysis copy**, keeping channels and the actual placement duration:
+
+```powershell
+ffmpeg -n -i 'path/to/selected-track.wav' -vn -c:a pcm_s16le 'path/to/job/disposable/analysis.wav'
+```
+
+For MP3/AAC or edits, first establish the final placed start/duration and decoder
+delay; analyze the conformed placed audio. Register the original and derived
+WAV hashes and conversion command. The JSON hashes the analyzed WAV, not the
+original compressed file; keep that mapping explicit. Never change the played
+audio just to satisfy analysis. The JSON output path must be new; the helper
+refuses to overwrite any existing output or input.
+
+Output fields:
+
+| Field | Meaning |
+|---|---|
+| `source_sha256` | Identity of the analyzed WAV bytes |
+| `fps` | Reduced rational frame rate; use exactly this rate in the composition |
+| `frame_count` | Ceiling of sample duration × FPS; last frame starts before audio ends |
+| `frames[i].rms`, `.peak` | Raw linear amplitude over a centered FFT window, mean channel energy; not LUFS or whole-program peak QA |
+| `frames[i].bands` | Fixed-floor, windowed FFT magnitudes mapped to 0–1 with offline attack/release smoothing |
+| `band_edges_hz` | Log-frequency band edges; sparse low-frequency bands can share their nearest FFT bin |
+| `fft_size`, `scale` | Reproducible analysis settings, including dB floor and smoothing times |
+
+The 24-band, 1024-sample, 35ms attack/180ms release defaults are analysis starting
+points; their aesthetic effect needs treatment selection. Silence produces
+zero, with no decorative minimum bar. Independent channel-energy averaging
+avoids false silence on opposite-phase stereo. FFT bands are uncalibrated
+visualization data, not a spectral metering instrument. Use 2048/4096 samples
+when low-frequency resolution matters; longer windows blur transient timing.
+This helper supplies an **amplitude envelope**, not a signed waveform trace or
+beat grid. Draw a true waveform from actual PCM samples or a verified existing
+waveform specialist; never label equalizers or invented bars as measured waves.
+
+Smoothing is computed once in source-frame order and baked into JSON. Rendering
+simply reads the requested frame; it never mutates a previous-frame accumulator.
+Expect CPU cost to grow with duration, FFT size and channel count. The helper
+caps analysis at 72,000 frames and fails on invalid/truncated PCM. An accepted
+PCM file still needs the separate audio QA required by Editing OS.
+
+## Frame-derived motion in HyperFrames
+
+Inline the reviewed JSON during build or stage it as a local build input; no
+render-time remote fetch. Use the same rational FPS and source-time mapping as
+the actual audio clip. An isolated visualizer begins at t=0. A trimmed/offset
+clip maps `source_time = output_time - placement_start + source_in` before
+indexing; silence/absent clips produce zeros. For loops, make the mapping and
+audio seam explicit. A changing clock invalidates all downstream evidence.
+
+For modest scenes, explicit GSAP frame sets provide simple random-access
+reproducibility. On each sized bar child (not its timed clip wrapper), schedule:
+
+```javascript
+const fps = fpsNumerator / fpsDenominator; // from the reduced JSON rate
+const tl = gsap.timeline({paused: true});
+for (let i = 0; i < analysis.frames.length; i++) {
+ const at = placementStart + i / fps;
+ analysis.frames[i].bands.forEach((value, b) => {
+ tl.set(barNodes[b], {scaleY: value, transformOrigin: '50% 100%'}, at);
+ });
+}
+// Add finite scene/treatment motion before registering the completed timeline.
+window.__timelines[compositionId] = tl;
+```
+
+This excerpt assumes the analyzed audio begins at source zero and is placed
+without cuts/stretching. Apply the mapping above for other cases. Set every bar's
+initial scale to zero through GSAP before `placementStart`, and schedule zero at
+the actual audio end if the composition continues. Give bars real fixed width
+and maximum height; their container must fit that height at the largest frame.
+Do not put conflicting initial CSS transforms or CSS transitions on those nodes.
+The root duration is the actual delivery duration, not a guessed song length.
+Audio uses the runtime's timed `` clip, never `.play()`.
+
+This approach costs `frames × bands` timeline sets. Benchmark a representative
+excerpt before a long song. If that cost is excessive, use a verified seekable
+runtime adapter that computes pure state from its requested time; do not switch
+to a timer or live audio playback to improve preview performance. DOM state
+must match when seeking to the same time in forward and reverse order.
+
+For energy-driven title/accent motion, derive the target from the recorded RMS
+and approved bounded gain. Keep the title readable and avoid a new focal event
+on every beat. Do not use dB-band values as a physical loudness claim. Any
+easing/filtering must be baked or a pure time function. Large glows and rapidly
+alternating brightness need specific visual safety review; calm/reduce motion
+when the selected treatment or accessibility requirement calls for it.
+
+## Lyrics and section progression
+
+Use a corrected, forced-aligned lyric source with the same audio hash, language,
+alignment model and correction identity as the played track. After editing,
+consume approved `retimed_words`. Generate phrases through the existing
+Captions engine under its adapter capability. A full-screen lyric stage is a
+layout choice; it does not create a second word clock.
+
+When reading LRC candidates, recognize metadata, offsets, repeated timestamps
+and blank lyric/gap markers. Validate nonnegative ordered times, preserve
+repeated verses, and verify ends against sung offsets/silence and actual track
+duration. Do not derive the final end as `start + 5`; do not silently drop
+malformed or duplicated lines. LRC line starts do not establish word-level
+alignment. Review both first and last onsets and interior drift; one global
+offset cannot fix tempo drift or text/audio mismatch.
+
+Use musical sections as evidence for scene planning, not automatic scene swaps.
+A verse can orient, a chorus can provide payoff, and a break can recover; map
+them to the actual editorial-intent roles when useful. Stable layouts can hold
+through a section. Change the treatment at a meaningful progression rather
+than cycling hue across the whole track. Credits come from the actual rights
+ledger; never insert vendor/generated-by branding by default.
+
+## Review points
+
+Record the first/last frame, silent/quiet/peak passages, each section transition,
+longest lyric, every chosen caption activation, peak geometry and glyph edge
+case in the existing review plan. Test target aspect ratio and 50%-linear-scale
+readability. Compare forward/reverse seek state and independent render output.
+Verify the actual encoded audio at head/middle/tail and after every cut/loop.
+Every new compression/export invalidates the previous final artifact hash.
+Platform upload limits are delivery inputs to verify at use, not copied static
+limits from the vendor skill. A passing helper test does not establish encoded
+playback, accessibility, lyric accuracy, graphics QA or publication readiness.
diff --git a/Editing_OS/Skills/audio-reactive-motion/SKILL.md b/Editing_OS/Skills/audio-reactive-motion/SKILL.md
new file mode 100644
index 0000000..bd046a3
--- /dev/null
+++ b/Editing_OS/Skills/audio-reactive-motion/SKILL.md
@@ -0,0 +1,113 @@
+---
+name: audio-reactive-motion
+description: Plan and author music visualizers, audio-reactive spectrum bars, amplitude-driven accents and verified lyric videos within Editing OS. Use for motion driven by an existing audio track; ordinary explanatory diagrams keep the existing Graphics engine route.
+---
+
+# Audio-reactive motion inside Editing OS
+
+This is an owned adaptation of ACE-Step's `acestep-simplemv` ideas, inspected
+remotely at commit `ca1e85fe9430179831e6bc6be790c332190a3866` on 2026-10-12.
+No upstream repository, scripts, models or dependencies were installed. This
+skill does not generate music or install ACE-Step/Remotion.
+
+Load [Master Prompt](<../MASTER_PROMPT.md>), [Taste Profile](<../TASTE_PROFILE.md>),
+[Tool Routing](<../TOOL_ROUTING.md>) and [Quality Standard](<../QUALITY_STANDARD.md>)
+first. Use the existing production-context, editorial-intent, taste-selection
+and applicable audio-plan contracts and the owned Orchestration Adapter. This
+workflow is a specialist recipe, never a competing approval or release gate.
+
+The routing update changes a governing-document hash. On resuming an existing
+job, run the adapter's live-hash preflight and refresh/reapprove affected
+contracts through the existing workflow; do not edit old approvals to appear valid.
+
+## Route the requested result
+
+| Request | Route and decision |
+|---|---|
+| Spectrum/music visualizer | This skill → owned offline audio analysis → bespoke HyperFrames composition |
+| Audio-reactive title or accent | This skill for measured energy; existing selected graphics treatment for layout/type |
+| Lyric video | This skill for scene/layout; existing WhisperX + Captions engine for verified sung-word timing |
+| Beat-cut montage or full music-led film | Available HyperFrames `music-to-video` workflow for planning; this recipe only where audio-reactive scenes help |
+| Talking-head explanation | Existing Graphics engine + `retimed_words`; music reaction must not replace spoken semantic anchors |
+| New song, cover, stem separation or repaint | Separate music-generation job; ACE-Step runtime is unavailable through this integration |
+
+Never install a missing vendor dependency to make this recipe work. Use the
+existing local renderer/runtime, or report the concrete missing capability.
+Read [IMPLEMENTATION.md]() when building/analyzing a scene.
+
+## Decide the scene before reacting to audio
+
+Establish the licensed source track, actual delivery geometry/FPS, language,
+audience, intended emotion, section progression and required lyrics. Keep the
+original track immutable. Author in the existing the selected external job workspace workspace.
+Record every background, audio track and font in the job's asset ledger with
+source/rights, purpose, local path and SHA-256. A repository software license
+does not establish music, voice, likeness or image rights.
+
+Choose a viewer task: feel a musical change, follow lyrics, identify a song, or
+understand audio evidence. Do not imply a decorative spectrum is calibrated
+measurement. Use one focal layer; title, lyric and visualizer each have a role.
+
+When appearance is unresolved, show 2–3 useful treatments on the **same real
+excerpt**, including a dense lyric/peak and a transition. Useful proposals:
+
+- restrained single-accent spectrum beneath a stable title;
+- lyric-first composition with small energy-driven accents;
+- image-led composition with subtle measured energy and clear type.
+
+These are options, not authorized defaults. Freeze the human's explicit choice
+in `taste-selection/v1`, including palette, typography, safe area, bar count,
+motion gain, smoothing and background treatment. Reuse a prior explicitly
+authorized look when it applies. The Taste Profile remains unchanged by this
+OS upgrade. Remove rainbow cycling, heavy glow or pulsing text unless chosen
+on actual material and still readable.
+
+## Preserve the two timing responsibilities
+
+**Music reaction** uses analyzed samples on the final music-placement clock.
+**Words** use corrected forced alignment and, after cuts, approved
+`retimed_words`. Beats do not decide word activation or explanatory reveals.
+If music is trimmed, moved, stretched, looped or mixed differently, regenerate
+the analysis for the actual placed segment, or document the exact source-time
+mapping and offsets. Do not analyze one track while playing another.
+
+LRC and ASR are candidate lyric inputs. Listen against authoritative lyrics,
+check names and repeated sections, then verify sung onsets and offsets. Do not
+retain incorrect timestamps merely because wording was corrected. Do not split
+line timestamps evenly into words, add a fixed -0.5s offset, or invent a final
+line duration. If singing defeats forced alignment, resolve the alignment and
+review evidence before production timed lyrics; a draft or static lyric card
+must be labeled accurately. A manually edited file alone is not alignment
+provenance.
+
+## Build and verify
+
+Use the installed HyperFrames core/animation contract: one paused, registered
+timeline, finite duration, local assets/fonts and framework-owned audio. Measure
+energy/spectrum offline; visual state must be reproducible at any requested
+time, including backwards seeks. No live WebAudio analyser, CSS transitions,
+autoplay timer, network asset or render-time random motion.
+
+Keep text stable while the spectrum moves. Allocate clearance for peak bar
+height and any title motion; design portrait/landscape independently from the
+actual delivery context. Background art must leave space for lyrics; text that
+must remain editable belongs in the composition. Typography baked into an
+image follows the owned Ideogram route and its existing cost gate.
+
+Before a long render, check silence, a quiet passage, a peak, section changes,
+longest lyric, final lyric, first/last frames and peak layout density. Review
+forward/backward seeking at the same frame, glyph coverage, phone-scale text,
+no clipping/overlap, real spectrum response and clean head/tail audio. Frame
+analysis is not beat detection, forced alignment, loudness QA or graphics QA.
+
+Use actual HyperFrames lint/check and capture their logs; bespoke scenes need
+real graphics QA rather than the generic planner's seven-family coverage claim.
+Record applicable caption and audio QA through the existing evidence envelopes.
+Run encoded-artifact Quality Engine checks, the declared independent repeat
+render or explicit scoped waiver, and exact-hash human playback/device review.
+Re-encoding for a size limit creates a new artifact requiring new hash-bound
+QA/review. Only Quality Engine readiness plus adapter publication authorization
+permits a publication-ready claim.
+
+Source and rejected defaults are documented in the
+[public source and scope notes](../PROVENANCE.md).
diff --git a/Editing_OS/Skills/motion-graphics-recipes/BROLL.md b/Editing_OS/Skills/motion-graphics-recipes/BROLL.md
new file mode 100644
index 0000000..26655fa
--- /dev/null
+++ b/Editing_OS/Skills/motion-graphics-recipes/BROLL.md
@@ -0,0 +1,71 @@
+# Transcript-timed motion B-roll
+
+Read with [SKILL.md](). Start from sentence/scene analysis, not a quota
+of clips per minute. Draw the product, document, relationship or result that
+clarifies this particular spoken idea. Keep the speaker visible when expression
+is the proof or the emotional payoff. A cutaway during a hook can be correct
+when it shows the promised result; no universal first-second exclusion applies.
+
+## Plan the visual coverage
+
+For each proposed graphic record scene/beat IDs, approved output in/out frames,
+covered clause, exact word IDs, proof source, layout, subject/caption clearance,
+state sequence, transition purpose, settled reading interval and failure check.
+Make the final hold fit the explanatory clause, not an arbitrary refresh limit.
+If cues compete, simplify or remove the weaker cue rather than truncating meaning.
+
+| Coverage | Choose when | Verify |
+|---|---|---|
+| Full-stage cutaway | The idea requires an inspectable process/result/comparison | The proof is readable; audio and word clock continue; return to speaker is motivated |
+| Side panel or stage PiP | Speaker presence matters alongside the explanation | Clearance covers all PiP positions, camera changes, captions and platform UI |
+| Transparent overlay | A small, anchored visual explains the point on footage | Real alpha, background contrast and subject clearance at the entire motion envelope |
+| No graphic | The speaker already communicates it better | Preserve the delivery and deliberate recovery pause |
+
+Select supported `stat`, `comparison`, `process`, `concept_diagram`, `quote`,
+`asset_focus` or `emphasis` through the existing Graphics engine. Continuous
+container morphs, cursor interactions, drag/drop, UI simulation and travelling
+objects require bespoke HyperFrames authoring; these are not new planner enums.
+
+## A persistent object as a connective device
+
+Use continuity when the viewer needs to recognize the same thing changing state:
+document → queued item → processed result, or question → options → selected
+answer. Choose identity cues that survive the change (label, icon, outline or
+position). Morph container bounds/radius deliberately; preserve readable content
+until its meaning has been absorbed. Stage old-content exit and new-content
+entrance separately so overlapping text never becomes an accidental third state.
+Prefer a clear cut or dissolve when the underlying objects are unrelated.
+
+Plan cursor approach, hover, contact, action, result and recovery. The cursor
+must hit the real target in transformed screen coordinates. Camera scale changes
+must preserve the target/cursor relationship and viewport clearance. Do not
+animate cursors to imply interactions the product cannot perform. Typing and
+count-ups are demonstrations, not word-timing or measured-latency evidence.
+
+For clip-local motion use `local_time = approved_output_time - clip_in_time`.
+Example: a retimed reveal at 12.40s in a clip starting at 10.00s activates at
+2.40s locally; at 30fps those are output frames 372 and 300, local frame 72.
+If footage is cut, obtain a new approved clock before recomputing the anchors.
+Use frame normalization at rational FPS rather than decimal filename arithmetic.
+
+Measure type at the smallest camera scale and maximum content length. Persistent
+objects need distinct entrance, transform, settled proof and exit states; a smooth
+morph does not excuse an unreadable result. Damped easing may suit the chosen
+look, but spring overshoot is not automatic. Reduce motion before shrinking text.
+
+## Review and handoff
+
+Capture on/around semantic anchors, old/new-content overlap, camera extrema,
+PiP changes and the final settled frame. Composite alpha assets on both light
+and dark real backgrounds to check edge halos and contrast. Verify that the
+actual codec/pixel format contains alpha; a `.mov` extension proves nothing.
+If the local renderer cannot export the required alpha codec, supply a verified
+composite or report that limitation rather than describing an opaque clip as
+transparent. Never use a black background as an implicit matte.
+
+Deliver a small approved asset set, editable HyperFrames composition and one
+timing/decision file. Record source hashes, output slot, exclusive end frame,
+FPS, proof/illustration labels and whether the last state is intentionally held.
+If a slot exceeds the asset's animation duration, declare/test the hold; never
+silently stretch speech or loop the graphic. Preview preserves original audio
+unless approved audio work changes it. Exact encoded QA remains mandatory.
diff --git a/Editing_OS/Skills/motion-graphics-recipes/EXPLAINERS.md b/Editing_OS/Skills/motion-graphics-recipes/EXPLAINERS.md
new file mode 100644
index 0000000..c89e19f
--- /dev/null
+++ b/Editing_OS/Skills/motion-graphics-recipes/EXPLAINERS.md
@@ -0,0 +1,104 @@
+# Product explainer construction
+
+Read with [SKILL.md](). These are three narrative tools; duration,
+energy and branding come from the actual brief. Product films retain the
+product-launch/custom-video route. They do not become a standalone short-motion
+job merely because the visuals are animated.
+
+## Choose the explanation mechanism
+
+| Mode | Viewer needs | Narrative construction | Main risk |
+|---|---|---|---|
+| Demonstration | See what a real action produces | Relevant problem/input → action → inspectable result → payoff | A beautiful reconstructed UI implies unsupported behavior |
+| Continuous journey | Understand what passes through a workflow | One identifiable object visits ordered stations → result → overview | The camera or metaphor hides causality/order |
+| Kinetic promo | Remember a concise value proposition | Earned hook → a few claim/proof beats → signature idea → readable ending | Speed, decorations and music erase the message |
+
+Use existing scene roles (`proof_demonstration`, `mechanism_explanation`,
+`contrast_transformation`, `payoff`, etc.) in the editorial contract. These
+mode names are recipe labels, not schema values.
+
+Verify product features, labels, outcomes, integration names and CTA against
+supplied evidence/current authoritative product material. A diagram inspired by
+a site is illustrative. A polished reconstructed interface is not screen-recorded
+proof. Keep a source screenshot/capture and version/date for reconstruction;
+label mockups and sample data. Prefer real capture where exact behavior matters.
+Do not hide errors, waiting time or qualifying copy to imply a false capability.
+
+## Demonstration: action and result
+
+Begin with the relevant question or result when useful; an obligatory
+"Introducing" scene consumes attention without necessarily giving value.
+Build chapters around concrete tasks. Orient the viewer, move close to the
+control, show action, hold the result, then recover context before the next task.
+
+Camera movement should reveal detail or reconnect context. Compute framing from
+actual transformed bounds, including cursor, result and longest label. Avoid
+following every typed character if it makes the content unstable. Text can wrap
+and reflow deliberately; do not globally force nowrap. Size type for the final
+device rather than copying web UI pixel sizes. Reduce chapter count when the
+requested duration cannot fit readable results; do not compress every hold.
+
+Each chapter needs input, actual action, truthful result and a failure condition.
+Claims with quantities need units/source; illustrative progress must not imply
+benchmarked speed. Show integrations once with honest labels rather than
+duplicating tiles to suggest a larger supported ecosystem. Blank/skeleton bars
+can also imply data: label illustration and avoid a quantitative scale.
+
+## Continuous journey: one object, stable geography
+
+Choose an object native to the workflow: a request, file, message or record.
+Keep recognizable identity as its state changes. Place each station according
+to actual process order on a stable world layout. Every visit must cause a
+visible, correctly labeled state change; remove stations that add only motion.
+
+Plan object contact and station response before camera embellishment. Track the
+object in world coordinates; derive camera framing and contact points from the
+same coordinates. During interaction, frame the station/result; during travel,
+lead toward the next destination. At payoff, hold the result before an overview
+reveals how the stations connect. If the overview makes labels illegible,
+preserve recognition with selective emphasis rather than tiny explanatory copy.
+
+Camera follow must be analytic or pre-baked on a fixed time grid, with specified
+initial conditions and interpolation. Do not integrate a spring once per
+requested render frame: backward/out-of-order seeking would change the result.
+Choose damping and path speed from readability, not assumed physics constants.
+An object's playful impact is an optional selected treatment, not evidence of
+causal product behavior. Captions remain available if required; a cinematic
+one-take constraint cannot ban accessibility text.
+
+Loops are optional and cannot reverse a real irreversible process as if that
+were product behavior. A metaphorical reset must read as a loop device. Check
+position, velocity, camera, station state, opacity and audio tail across the
+seam. Compare the last encoded frame to the first and assess the first step
+after wrap; copying endpoint positions alone does not prove a smooth loop.
+Keep a finite export duration and declare intentional looping/holds to QA.
+
+## Kinetic promo: controlled energy
+
+Choose a small number of defensible claims and one distinctive visual metaphor.
+Carry an object/shape across a transition only when it connects meaning or
+directs attention. Establish carry-out/carry-in position, size, direction and
+color continuity; keep one focal event per beat. Alternate impact with readable
+settled holds so the payoff registers. A still hold is legitimate motion design.
+
+Use a verified grid from the placed music only for flexible accent timing.
+Speech and reading load govern narrated scenes. Do not force all reveals onto
+subdivisions, add a HUD/timecode, spin objects or add saturated fills because
+the upstream style did so. UI chrome, grain, depth and blur must earn their
+place in the selected treatment; check phone legibility and flashing risk.
+Review the shortest text exposure and transition peak, not only hero stills.
+
+## Build and review
+
+Use native HyperFrames scene/subcomposition structure and the installed
+animation adapter. Local fonts require verified load/glyph coverage; brand
+assets require the job rights ledger. Keep audio framework-owned and follow
+[SOUND_DESIGN.md]() when a mix is requested. Neither synthetic
+music nor a sound library is an implicit part of this integration.
+
+Before a long render, review a complete representative interaction, longest
+copy, densest scene, camera extrema, journey overview or carried transition,
+and end card. Seek these times in both directions. Record placeholder content
+and unresolved decisions plainly. Deliver editable composition, approved assets,
+review copy and decision/evidence links through the existing storage-light
+workflow. A rendered demo still requires the existing exact-artifact release gate.
diff --git a/Editing_OS/Skills/motion-graphics-recipes/SKILL.md b/Editing_OS/Skills/motion-graphics-recipes/SKILL.md
new file mode 100644
index 0000000..cff9b54
--- /dev/null
+++ b/Editing_OS/Skills/motion-graphics-recipes/SKILL.md
@@ -0,0 +1,107 @@
+---
+name: motion-graphics-recipes
+description: Plan and author transcript-timed motion B-roll, product UI demonstrations, continuous workflow journeys, kinetic promos, subject-mask handoffs and motivated sound passes within Editing OS. Use these recipes for explanatory or product motion; music visualizers and sung lyrics use audio-reactive-motion.
+---
+
+# Motion graphics recipes inside Editing OS
+
+Owned craft adaptation of [Barty-Bart/motion-graphics](https://github.com/Barty-Bart/motion-graphics/tree/3d83d987d658601d8a1269eb691622bdcd427335),
+inspected remotely on 2026-10-13. No upstream repository, scripts, templates,
+fonts, sound library, installer or model was saved or executed. Read only the
+recipe needed for the requested result. The upstream names describe creative
+approaches, not installed commands or approval authority.
+
+Load [Master Prompt](<../MASTER_PROMPT.md>), [Taste Profile](<../TASTE_PROFILE.md>),
+[Tool Routing](<../TOOL_ROUTING.md>), [Quality Standard](<../QUALITY_STANDARD.md>)
+and the governing handbook before production. Create/validate the existing
+production context and use the owned Orchestration Adapter preflight. This is
+an OS skill integration; it does not authorize a new video job or a taste change.
+
+## Choose by viewer task
+
+| Requested result | Read | Existing owner / capability |
+|---|---|---|
+| Illustrate spoken ideas with animated cutaways or panels | [BROLL.md]() | Graphics engine for supported families; bespoke HyperFrames for persistent-object/UI choreography |
+| Explain a product through demonstrable interface actions | [EXPLAINERS.md](), demonstration mode | Product-launch workflow for commercial briefs; existing editorial contracts and HyperFrames |
+| Follow one object through a workflow in one continuous view | [EXPLAINERS.md](), journey mode | Bespoke HyperFrames; truthful process order and camera choreography |
+| Short energetic product teaser or kinetic promo | [EXPLAINERS.md](), kinetic mode | Product-launch/custom-video workflow for the film; short motion-graphics workflow only for an applicable standalone unit |
+| Isolate a person/product/hand, or put graphics behind a subject | [SUBJECT_MASKS.md]() | Existing verified mask/NLE capability or supplied matte; automatic segmentation is conditional, not installed here |
+| Add effects/music to an existing composition | [SOUND_DESIGN.md]() | Existing audio-plan, available mix tools and Quality Engine |
+| Spectrum, amplitude reaction, verified lyric video | [audio-reactive-motion](<../audio-reactive-motion/SKILL.md>) | Offline workbench analysis plus existing caption/renderer ownership |
+
+Recipe selection does not replace HyperFrames deliverable routing. Load its
+installed entry/core/animation/CLI skills only as needed for actual authoring.
+Do not invoke a repository setup command, copy its renderer, or install missing
+dependencies to make a recipe appear available. Reuse verified local tools;
+report the specific missing capability and continue independent planning.
+
+## Shared production rules
+
+- Derive the brief from supplied footage, product evidence, current references,
+ audience and delivery facts. Use actual rational FPS and dimensions. Keep one
+ untouched source and author in the existing the selected external job workspace workspace.
+- Write scene intentions in `editorial-intent/v1`, using existing semantic roles
+ rather than creating new enums for these recipe names. Show the viewer's
+ entering question, proof, change and exit understanding.
+- Speech reveals use corrected forced alignment and approved post-cut
+ `retimed_words`. A cue-level SRT/VTT, raw ASR, character count or beat grid
+ cannot supply production word timing. Music-only accents use the placed
+ audio clock. Any cut/voice/music-placement change invalidates affected mappings.
+- When appearance is unresolved, show 2–3 directions on the same real excerpt,
+ including a dense frame and transition. Freeze the explicit choice in the
+ existing `taste-selection/v1`; reuse applicable authorized project decisions.
+ Morphs, springs, camera moves, blur, typography, palette and sound are choices,
+ not mandatory house styling. Keep a valid no-graphic/no-SFX option.
+- Keep content and rights traceable: source ID, local path, SHA-256, rights,
+ intended use and scene IDs for each asset. Illustration is distinct from
+ evidence. Do not fabricate UI behavior, quantities, percentages, testimonials,
+ integrations or destinations. A code license does not license every asset.
+- Keep extra cue/matte/timing information in one readable job decision artifact,
+ linked and hashed from supported contract references/evidence. Existing
+ schemas reject unknown properties: do not inject recipe fields into them or
+ invent an adapter capability. Use actual schema and engine interfaces.
+
+## Native runtime and final review
+
+For reference identity, physical object motion, material/shader reveals,
+imported clip/morph animation or shared website scenes, load the expanded
+[studio 3D skill](<../studio-3d-objects/SKILL.md>). Keep this recipe's semantic
+anchors and explanatory holds; deeper 3D is not a reason to hide proof, shorten
+reading time or introduce another clock. Website/optimizer runtimes remain
+conditional on verified local availability.
+
+When a B-roll/product scene needs a closer reference identity, load
+[procedural motion design](<../procedural-motion-design/SKILL.md>) for measured
+composition, material/type/light rules and coherent motion. Use the existing
+[Studio Objects 3D](<../studio-3d-objects/SKILL.md>) route for a real-looking object
+that opens, stacks, stamps or refracts; an isometric drawing is a different look.
+
+Use the actual installed HyperFrames contract: finite composition root and
+timed clips/media, one paused registered timeline per composition, local fonts
+and assets, framework-owned media playback. Do not substitute upstream
+`window.seek`, an autoplay clock, CSS transitions or a custom audio scheduler
+for framework seeking. Analytic or baked camera paths must reproduce the same
+state after forward, backward and repeated seeks. Avoid render-time randomness
+and network loads. Do not upgrade a project's pinned renderer during production
+without checking the existing project's compatibility workflow.
+
+Review entrance, semantic activation/contact, transition midpoint, settled hold,
+exit, densest frame and both endpoints. Holds need reading/recognition time
+after motion settles. Check phone-scale type, captions, proof and subject
+clearance; blur must not erase the information being demonstrated. A handoff
+records integer in/out frames with exclusive ends, rational FPS, duration,
+source/output mapping, alpha convention when applicable and what is illustrative.
+Rendered overlays are editable assets in the finishing workflow, not a claim
+of native editable CapCut project transfer.
+
+Capture actual graphics, applicable captions and audio QA in existing evidence
+envelopes. Bespoke scenes require bespoke review; the generic graphics planner
+does not validate every UI/camera/matte technique. The encoded artifact still
+needs full Quality Engine checks, independent repeat rendering or its declared
+waiver, and exact-hash human playback/device review. Only Quality readiness and
+adapter publication authorization permit a publication-ready claim.
+
+Changed Tool Routing hashes require live preflight and refresh/reapproval of
+affected contracts when resuming jobs; never rewrite prior approvals to match.
+See the [public source and scope notes](../PROVENANCE.md)
+for source coverage, rejected defaults, verification and capability limits.
diff --git a/Editing_OS/Skills/motion-graphics-recipes/SOUND_DESIGN.md b/Editing_OS/Skills/motion-graphics-recipes/SOUND_DESIGN.md
new file mode 100644
index 0000000..3799394
--- /dev/null
+++ b/Editing_OS/Skills/motion-graphics-recipes/SOUND_DESIGN.md
@@ -0,0 +1,75 @@
+# Motivated sound pass
+
+Read with [SKILL.md](). Method inspiration: Bart's sound-effects recipe,
+which credits Vox (@Voxyz_ai). Carry forward cue-based verification and review
+of the encoded mix. No upstream sound files, manifest or sound-pass script are
+installed here. Use supplied/licensed local assets or the existing media workflow
+under the job's permissions; generated sound is a separate chosen capability.
+
+## Cue by visible event and meaning
+
+Read the approved composition/timeline first. Scene detection only proposes
+events; it cannot tell whether an effect is justified. Give each cue a stable
+ID, scene/event ID, output contact/peak frame, function, asset ID/hash, trim,
+placement offset, gain/fade, optional beat relation and listening check. Store
+this in the existing job decision artifact with its path/hash and link it from
+the job review notes. Describe the relevant checks in the actual `audio-plan`
+fields (`scene_audio_roles`, `masking_intelligibility_checks`, `sync_evidence`).
+The schema has no generic `references` field; do not append unsupported fields.
+
+| Event | Useful sound role | Placement check |
+|---|---|---|
+| Cursor contact / control activation | Small tactile confirmation | Audible transient aligns with visible contact, not file start |
+| Significant movement / handoff | Direction or energy accent | Fit attack/body/tail to motion; pre-roll only when it serves the event |
+| Important result | Recognition/payoff | Peak supports recognition after the result becomes visible |
+| Build toward a reveal | Anticipation | Tail resolves on the chosen reveal without masking preceding speech |
+| Sustained typing or action | Low-level texture when useful | Trim/loop matches action; verify joins and repeated sound fatigue |
+| Recovery / emotional pause | Silence or continuity | No obligatory effect/bed; preserve the intended pause |
+
+Do not place a whoosh on every cut, enforce one effect on every cue, or assume
+a fixed two-frame offset. Choose fewer distinct sounds whose timbre matches
+the actual material. File leading silence and internal peak matter: measure
+and audition the sound's contact point, then align that point to the event.
+
+## Music clock and permissions
+
+Select music from material/emotional intent and the existing explicit taste
+choice. Record creator, source, rights, use case, local hash and any credit or
+redistribution conditions for every used file. Verify relevant current source
+terms when sourcing media. A software MIT license and an upstream library's
+CC0 label do not establish rights to arbitrary replacement tracks. The recipe
+does not restrict legitimate user-licensed assets to a two-license whitelist.
+Do not bundle, commit or distribute raw restricted audio as reusable skill media.
+
+When beat mapping helps, inspect the actual placed track. Verify downbeats and
+tempo changes against audible events/waveform across the head, middle and tail;
+kick energy alone does not prove every genre's beat or a constant tempo. Report
+uncertain/half-time/offbeat detection plainly. Recompute after trims, loops,
+stretch or placement changes. Prefer adjusting flexible accents or music placement
+inside approved constraints; changing an approved speech cut needs a new timing
+decision/approval. Meaning and intelligibility take precedence over beat error.
+
+## Mix, measure and listen
+
+Use existing `audio-plan/v1`: source assessment, restoration decisions, scene
+roles, masking/intelligibility, synchronization and project delivery targets.
+Dialogue priority is normally appropriate for explanation, while a music-led
+piece may have a different declared primary role. Fixed gain differences and
+ducking depths are starting experiments, not guarantees. Audition speech with
+effects/music on headphones and the target phone; inspect mono compatibility
+and any channel-dependent loss.
+
+Use verified existing audio mix tools; keep runtime media playback framework-owned.
+Measure the final encoded artifact for integrated loudness, loudness range,
+true peak, silence and decode integrity against the delivery spec. True peak
+uses dBTP; do not confuse it with sample peak dBFS. There is no universal
+-16 LUFS/-4 dB ceiling in this recipe. Changing the mix/re-encoding creates a
+new artifact hash and invalidates affected final review evidence.
+
+Review frames plus waveform around contact, longest effect, strongest reveal,
+densest speech, head/tail and every music/effect seam. These diagnostics prove
+placement, not that the sound is appropriate. Give the human the riskiest
+timestamps as review aids while retaining the required complete encoded playback
+and all Quality review points. Five spot checks cannot replace complete review.
+Capture actual measured results, accepted rights/credits, cue changes and audio
+QA in existing envelopes before the Quality/adapter publication gate.
diff --git a/Editing_OS/Skills/motion-graphics-recipes/SUBJECT_MASKS.md b/Editing_OS/Skills/motion-graphics-recipes/SUBJECT_MASKS.md
new file mode 100644
index 0000000..0d2304c
--- /dev/null
+++ b/Editing_OS/Skills/motion-graphics-recipes/SUBJECT_MASKS.md
@@ -0,0 +1,65 @@
+# Subject isolation and matte handoff
+
+Read with [SKILL.md](). This integration adds a governed workflow,
+not an installed SAM 2 backend. The upstream recipe downloads packages/models;
+those actions are not carried over. Inspect available local NLE, segmentation
+or supplied-mask capability first. Verify its actual version/interface on a
+short excerpt before promising automatic isolation. If unavailable, continue
+layout planning and use an existing manual mask/NLE route or supplied matte;
+state precisely which automatic capability is missing. Never claim the subject
+was isolated because a recipe was loaded.
+
+## Establish subject, frames and coordinate mapping
+
+Identify the intended person/object, source hash, source dimensions/orientation,
+actual frame timestamps, range and occlusions. Record inclusive start and
+exclusive end frames. A one-frame range is valid and must produce one mask;
+a source range `[100,160)` requires exactly 60 source-frame masks. Do not use
+a loop whose end condition drops a single-frame clip or duplicates boundaries.
+
+Use the exact decoded start frame to select positive/negative points or polygons.
+Map display/working coordinates back to source coordinates using actual resize,
+crop, padding and orientation transforms; do not assume a fixed 960px width.
+Record the transform and which object each prompt belongs to. Changed crop,
+orientation, source or chosen subject invalidates the prompts/mattes.
+
+VFR cannot be treated as constant FPS by choosing a convenient rate. Use actual
+timestamps or a declared, verified CFR derivative plus source-to-derivative map.
+Preserve the original and audio identity. For editorial cuts, map output frames
+to source frames using the approved EDL/retiming evidence; never attach mask
+frame N to output frame N after removing footage.
+
+## Validate a short difficult range
+
+Include motion blur, thin edges/hair, changing lighting, occlusion, disocclusion
+and any camera cut. Review the matte overlay and composites on light/dark
+backgrounds. Verify no identity switch, hole, edge chatter, spill, lag or missing
+frame. A green diagnostic tint is a mask preview, not the selected finished look.
+Binary segmentation is not a fine alpha matte: do not imply that simply blurring
+its edges recovers hair/transparency. Use a verified matting refinement or report
+the limitation when those edges matter.
+
+For chunked propagation, an overlap can seed the next chunk, but assign each
+source frame exactly once in the final sequence. Check first/last frames of
+every chunk and tracking after occlusion. A scene cut requires a fresh subject
+prompt/verification, not blind carryover of the previous mask. Verify frame count
+against the declared range and fail on truncated source decode.
+
+## Composite and deliver
+
+Record white/black meaning, alpha depth, dimensions, frame indexing, rational
+FPS/timestamps, source range/hash, crop transform, tool/model identity, refinement
+settings and output path/hash. A mask sequence is permitted when the deliverable
+needs it; keep intermediates in one disposable work directory and retain only
+the approved matte/overlay and reproducibility metadata after successful QA.
+
+Specify straight versus premultiplied alpha and check edge halos. Verify actual
+alpha codec/pixel format in the export and reopen it in the finishing app.
+For graphics behind a person, layer background → graphic → isolated foreground,
+with accessibility captions separately positioned. Check the foreground at
+motion extrema; a correct mask does not guarantee safe caption/graphic layout.
+Retain original audio unless a separately approved audio operation changes it.
+
+Mask QA supplements graphics/layout QA and the encoded Quality review; it
+does not invent a new evidence-type enum or grant publication authority.
+Never upload private footage or fetch model weights as an unannounced fallback.
diff --git a/Editing_OS/Skills/procedural-motion-design/DEPTH_AND_MOTION.md b/Editing_OS/Skills/procedural-motion-design/DEPTH_AND_MOTION.md
new file mode 100644
index 0000000..34404f1
--- /dev/null
+++ b/Editing_OS/Skills/procedural-motion-design/DEPTH_AND_MOTION.md
@@ -0,0 +1,120 @@
+# Depth and motion that support the identity
+
+Read with [SKILL.md](). For the existing photographed-object look, use
+[Studio Objects 3D](<../studio-3d-objects/SKILL.md>) and its owned starter/ops
+guidance after verifying the current runtime. Do not import Animate's kit or
+describe its planned ray-marched WebGL style as an installed capability.
+
+## Choose the depth representation
+
+| Representation | Useful for | Do not imply |
+|---|---|---|
+| Flat/vector | Truthful diagrams, type and simple relationships | Physical material or volume from a drop shadow alone |
+| Layered 2D / 2.5D | Foreground/background hierarchy, restrained parallax, captured UI surfaces | A hinge, occlusion or changing reflection unsupported by the source image |
+| Parallel/isometric projection | Device structure, stacks and paths with consistent projected axes | Lens perspective, photoreal studio material or true transmitted optics |
+| Real 3D / Three.js | Opening folders, stacking, stamping, filing, refracting and changing viewpoint | A verified look merely because geometry renders without error |
+| Photoreal still | A fixed hero with modest camera/position movement | Multiple continuous action states from unrelated generated shots |
+
+Use the simplest representation that actually supports the required action and
+selected identity. A real-looking object must keep coherent dimensions, pivot,
+surface detail, contact, light and camera when it moves. A stylistic isometric
+diagram may intentionally omit cast shadows; a studio object usually needs
+them. Neither route is a universal prescription.
+
+## Material and camera specification
+
+Define stage, object scale, projection/lens intention, camera pose and target,
+key/fill/environment, contact/cast shadow, surface roughness/metalness/clearcoat,
+glass settings, tone mapping and output color. Record the verified local
+Three.js version and matched addons. Freeze shared choices so neighboring shots
+occupy one world. Imported models/textures require asset hashes, rights and
+native-detail checks; they are not silently downloaded by this skill.
+
+The approved Studio Objects parameters are a useful scoped starting point, not
+physical calibration or every-job defaults. Check the material at the actual
+pose and exposure: bevels and reflections establish form; larger blur does not
+repair incorrect light. Screen contents must remain actual supplied UI evidence
+or an explicitly illustrative graphic. A refractive material needs the correct
+transmission/alpha/layer configuration for the installed renderer; verify the
+object visible through it, not just the outer glass silhouette.
+
+Review near/far scale, foreshortening, silhouette, object/background separation,
+depth order, contact/shadow and font texture sharpness. Keep important labels
+as stable DOM overlays or verified world-space print intentionally; perspective
+compression can make even a large texture unreadable. Load fonts before drawing
+CanvasTextures and redraw after load when necessary. Treat color roles and light
+settings separately from arbitrary screenshot palette averages.
+
+## Plan a complete action
+
+For each scene, state initial pose, anticipation where useful, contact/reveal,
+settled result, readable hold, exit and incoming focal point. Name object/camera/
+crop movement, its coordinate space and preserved properties. Keep contact
+events tied to exact approved semantic anchors; nonsemantic anticipation can
+lead without showing the result early. A universal 60ms early reveal, fixed
+sentence offset or spring preset must not move the meaning cue.
+
+Examples of staged rather than simultaneous interpolation:
+
+- Filing: rise above the slot, align, then lower into it without intersecting panels.
+- Hinge: rotate around the actual edge/pivot while the base and printed label
+ remain attached; hold the content reveal before closing.
+- Stack: separate enough to read hierarchy, then settle with collision/contact
+ clearance; keep order and label identity during overlap.
+- Stamp: approach, contact on the anchor, recover, then exit clear of the text;
+ derive the impression from the contact event rather than an independent clock.
+- Camera follow: aim at the actual moving subject or a bounded station/object
+ blend; choose framing from its full action envelope, including the tallest pose.
+
+A morph preserves an identity cue and a coherent silhouette correspondence.
+Extreme aspect-ratio changes can pinch or self-intersect; use staged geometry,
+matching outlines, a truthful cut or a simpler transition when needed. Before/
+after type should not overlap into an accidental third meaning. Object motion
+and camera motion must not independently carry the subject outside the frame.
+
+## Determinism and integration
+
+Use the installed HyperFrames core and matching Three adapter: finite root and
+sub-composition duration, local import map, explicit readiness for render-critical
+assets/compute, and a pure `renderAt(time)` driven by actual framework seeking.
+For sub-compositions, verify whether the incoming event time is global or local
+in that runtime and convert exactly once using the host offset. Use the existing
+studio helper only after verifying its actual timing convention.
+Some installed linters cannot discover timeline registration inside an imported
+helper. Expose the returned paused timeline under the matching
+`window.__timelines[compositionId]` key in the scene when that diagnostic occurs;
+do not create a second competing timeline to satisfy a static check.
+Stage required local modules/assets beneath the job's served root and use
+relative URLs, including addon imports. A diagnostic opened from `file://`
+may load absolute file URLs that the native HTTP render/player correctly blocks.
+Validate dependencies in the actual compiled render context, not only a direct
+browser-file preview.
+
+Reset every state variable from time, including backward seeks, textures,
+visibility, camera, shadow and material changes. Compute spring responses
+analytically or bake fixed-step simulation once with recorded seed/initial
+conditions; never integrate based on the order frames were requested. Layered
+2D cannot mask a stateful-camera bug. Stepped medium cadence is optional; quantize
+pose/texture independently from captions/media so spoken onsets stay exact.
+
+Verify the chosen WebGL environment for production 3D. Prefer hardware for
+throughput when its actual repeated output passes the declared policy. An
+explicit software profile can retain real 3D geometry/materials; verify its
+full-size appearance, capability and acceptable render cost before selecting it.
+A small software diagnostic does not establish production speed or a matching
+GPU result. Record browser/GPU/renderer facts and compare decoded repeat renders
+on the declared environment. Motion blur/transmission/antialiasing support and
+cost must be tested on a short difficult scene before enabling them broadly.
+If unavailable, report the capability limit rather than silently flattening the
+requested material/action or fetching a new dependency.
+If an actual repeat mismatches, isolate pose/seek state, capture and encoding
+on a short fixture, changing one verified setting at a time. A matching midpoint
+does not prove a full sequence reproducible. Do not average away differing pixels,
+substitute a similar-looking render or issue a waiver yourself. Retain the failed
+comparison and apply the existing Quality policy to the actual chosen environment.
+
+Sample the first pose, contact, extreme pose, transition midpoint, settled result,
+exit and final frame. Seek each frame forward, backward and repeatedly. Review
+phone-scale type, clipping, captions/PiP, alpha and actual encoded detail. A
+generic canvas/3D successful render remains subject to graphics evidence,
+Quality checks and exact-hash human approval.
diff --git a/Editing_OS/Skills/procedural-motion-design/MEDIUM_RECIPES.md b/Editing_OS/Skills/procedural-motion-design/MEDIUM_RECIPES.md
new file mode 100644
index 0000000..6c6f191
--- /dev/null
+++ b/Editing_OS/Skills/procedural-motion-design/MEDIUM_RECIPES.md
@@ -0,0 +1,68 @@
+# Procedural media and their identity checks
+
+Read with [SKILL.md]() and STYLE_IDENTITY. These seven vocabularies were
+adapted from remotely inspected Animate style guidance. Their source demos and
+drawing kits are not installed or certified here. Pick a medium only when
+the material/reference and explicit human choice warrant it. Recent Studio
+Objects approvals remain applicable where real object realism is the task.
+
+| Medium | Construct the identity | Motion choice | Check the distinctive failure |
+|---|---|---|---|
+| Cut paper | Layered silhouettes with intentional torn edges, paper thickness and contact/drop shadows; texture clipped to the material | Pose changes/drawn or cut transitions may use declared stepped cadence | Generic vector fills plus noise do not read as paper; tear/shadow scale must follow object scale |
+| Crosshatch ink | Directional hatching/stipple carries shading; line and fill texture live in world/object coordinates | Optional seeded line boil with stable underlying construction | Texture swims under a camera pan; incoherent hatch direction or tremor erases detail |
+| Riso print | Limited spot-ink roles, halftone density, controlled registration offset and overprint/knockout behavior | Declared print cadence; pattern moves with the printed surface | RGB gradients/glow replace print structure; moiré, fringes or compression destroy text |
+| Sketchbook | Graphite construction → settled ink → selective colored mark; paper context and meaningful mark hierarchy | Drawing gesture follows the actual path; optional limited boil | Global jitter makes diagrams/captions hard to read; colored fills obscure construction meaning |
+| Mathematical vector | Precise axes, units, equation/figure correspondence and stable variable identity | Derive graph, readout and labels from the same value; reveal in reasoning order | Pretty animation implies false quantities; displayed rounding, labels or transformed terms disagree |
+| Pixel | Author at declared native grid, limited palette, deliberate bitmap glyphs and nearest-neighbor scale | Whole-grid positions/poses; choose smooth grid scrolling or stepped poses explicitly | Fractional scale/camera movement introduces uneven pixels; small native glyphs fail at delivery size |
+| Isometric line illustration | Parallel projected axes, hidden-surface fills, consistent silhouette/internal-line hierarchy and slab thickness | Smooth or selected stepped component actions in coherent projected geometry | Hidden lines show through solids; projection/strokes change inconsistently during a camera move |
+
+## Keep medium rules separate from global production rules
+
+For print/paper/graphite, put the texture in the object/world coordinates so
+camera movement films a surface rather than sliding a screen filter over it.
+Use deterministic seeded construction and explicitly chosen variation intervals;
+repeated seeks to one frame must reproduce the same marks. Review on encoded
+frames for aliasing, flicker and compression loss. No obligation to add three
+background details, animated eyes or idle movement; stillness is valid when
+it helps the thought land.
+
+For line illustration, measure apparent weight relative to subject size and
+decide whether it remains constant on screen or scales with the object. A
+non-scaling outline and a shaded material are different identities; neither
+should accidentally emerge from a transform. Isometric/dimetric illustration
+can clarify topology without claiming photoreal depth or physical refraction.
+Use [DEPTH_AND_MOTION.md]() when real object action is needed.
+
+For pixels, keep native and output geometry separate. Prefer integer scale
+with a deliberate viewport/border or a separately authored variant; do not
+force every output into a grid that makes pixels uneven. Bitmap-style glyphs
+still need the required language, punctuation and rights. Designed type cannot
+replace accessibility captions with abbreviations.
+
+For math, retain evidence and exact relationships. Use text/state cues alongside
+color so identity is accessible. A precision change or complement rounding must
+not hide that the true value differs; show enough precision or a clear
+approximation mark. Decorative mascot/flash conventions are optional, not
+universal requirements for a rigorous diagram.
+
+## Content, type and runtime
+
+Generate actual factual/provenance-backed content before designing metaphors.
+A "winter" illustration does not prove a historic period or date. Figures,
+dimensions, UI interactions and quotations trace to named sources. Use verified
+local fonts/assets with glyph checks rather than silent system-font fallback.
+Keep narrative illustration, product-interface proof and caption transcription
+visually and semantically distinct.
+
+These media can use a native HyperFrames canvas or SVG layer, DOM typography,
+or an actually verified specialist. Keep each scene modular, reset drawing
+state at every requested time, and retain framework-owned audio/video. Canvas
+text is not automatically audited by DOM text checks: provide explicit bounding
+boxes/copy checks and inspect encoded text. Do not claim the generic Graphics
+planner renders every medium, or copy the upstream STYLE hooks as a second engine.
+
+One selected identity normally organizes a piece. A change of medium can signal
+before/after, memory or uncertainty when intentional and reviewed; upstream
+global helper-name collisions are not a creative reason to ban all mixed-media
+films. Isolate scene namespaces, shared tokens and media ownership through the
+actual composition contract instead.
diff --git a/Editing_OS/Skills/procedural-motion-design/PIPELINE.md b/Editing_OS/Skills/procedural-motion-design/PIPELINE.md
new file mode 100644
index 0000000..ffded7b
--- /dev/null
+++ b/Editing_OS/Skills/procedural-motion-design/PIPELINE.md
@@ -0,0 +1,90 @@
+# Carry the design through the existing pipeline
+
+Read with [SKILL.md](). This adaptation supplies craft choices inside
+the current editing workflow; it never creates a second `pieces/` runtime,
+provenance store or approval ladder. Actual job content stays under the selected external job workspace.
+Reusable executables stay in the toolkit workbench; disposable probes stay in the external workspace cache.
+
+## Planning to delivery
+
+| Existing checkpoint | Additional design decision | Reviewable result |
+|---|---|---|
+| Understand / production context | Actual reference regions, audience/message, delivery formats and capability/rights facts | Live governing hashes; named sources and deliberate assumptions |
+| Inspect / align | Source versus capture versus output time; actual retained speech | Corrected forced-aligned words; no raw-ASR timing substituted |
+| Story / scene intent | A reason each next scene follows; identity thread and source-backed proof | Existing scene roles, entering/exit state, duration rationale and failure conditions |
+| Rough cut / timing | Meaning before music; full explanatory/recognition holds | Reviewed EDL, approval and post-cut word clock |
+| Treatment | Same-material comparison of geometry/material/light/type/motion | Explicit selected taste tokens or hashed treatment artifact |
+| Graphics / 3D build | One world, useful actions, bounded camera, intentional state transitions | Supported Graphics family or verified bespoke scene, local assets and graphics QA |
+| Captions / audio / grade | Retained wording, subject-safe text, selected mix and correction strategy | Current specialist evidence bound to timeline/taste |
+| Variants / export | New compositions for requested shapes; actual stream/color/audio targets | Every realized variant gets its own encoded checks and review |
+| Deliver / learn | Name unmatched features and verified scope; preserve editable handoff | Quality readiness plus adapter publication authorization; scoped approved lessons |
+
+## Story grammar without fixed formulas
+
+Use the causal device that serves the actual message. The following are planning
+patterns, not new schema enums and not certified algorithms:
+
+- chronology: verified time order with coherent state changes;
+- one item through stations: track the item and show each actual transformation;
+- question to collection: each answer adds useful information, then a meaningful grouping;
+- goal and helper: obstacles and verified actions lead to the earned result;
+- carried subject through worlds: preserve identity while context changes;
+- process rebuild/loop: show real making steps; looping must not falsify irreversible events;
+- variation study: hold comparable subject geometry to compare treatments;
+- claim and proof: show inspectable evidence before expecting trust.
+
+Map these to the existing semantic scene roles. The upstream's F1–F8 labels,
+"proven" demos and strict beat/cut quotas are not local capability evidence.
+There is no universal silent opening, peak hit, accelerated journey, fixed
+hero or obligatory loop. Preserve a deliberate breath/held frame without
+forcing a blinking prop to pass a dead-beat checker. Callback, morph and hard
+cut are options whose purpose must survive the five-criteria filter.
+
+## Three clocks and assets
+
+Speech uses corrected forced alignment, approved EDL and `retimed_words`.
+Music uses the actual licensed placed segment and verified mapping. Visual
+simulation uses deterministic composition time. Record the conversions; neither
+sentence-length heuristics nor a nice music grid may substitute for the speech
+clock. A changed voice take, crop, source cut or track placement invalidates the
+affected captions, anchors, matte/track mapping and final review evidence.
+
+Use real product captures for behavioral proof. A screenshot on a 3D tablet
+can identify an interface but does not prove the animated action is supported;
+pair it with actual recording/state evidence or label the sequence illustrative.
+Read source detail at the maximum planned zoom. Track each asset's source/rights,
+path, hash, purpose and usage conditions. Do not automatically synthesize a
+soundtrack, contact a provider, capture an unrelated account or bundle restricted
+media because the upstream workflow offered it.
+
+Sparse effects align their audible contact/peak with visible events. Keep the
+selected dialogue/music priorities and measure the encoded mix using declared
+LUFS/dBTP/LRA targets. A waveform/RMS plateau does not prove sound fit, silence
+before payoff, intelligibility or listening quality. Preview must play the same
+track/placement/mix intended for export; a different temporary score needs an
+explicit draft label and cannot approve the final mix.
+
+## Responsive composition and testing
+
+Re-layout each requested aspect from its own content/task: subject scale,
+hierarchy, caption/PiP zones, line breaks, focal crop and camera extrema.
+Normalized coordinates help describe intention but do not prove a design fits.
+Do not stretch/crop a portrait finished render into a landscape deliverable.
+Pure crop variants are acceptable only when explicitly appropriate, verified
+and not missing material meaning. Use current platform safe areas rather than
+upstream fixed x/y coordinates. Unrequested variants are not implicit scope.
+
+Before a long render, test a difficult action, dense label, texture close-up,
+transition and first/last pose. Lint errors can disable downstream audits;
+zero sampled text is not success. Canvas/world text needs its own actual-copy,
+bounds and encoded-pixel review. Motion on twos can trigger freeze scanners:
+declare justified intervals in the spec and review them, rather than disabling
+the scanner or labeling every freeze intentional.
+
+Review repeated/backward seeks and an independent repeat render under the
+declared determinism policy. A WebGL driver or browser change is part of that
+environment, not an unnoticed replacement. Browser DOM checks and style metrics
+remain supporting diagnostics; use full decoded video/audio, actual geometry,
+artifact-specific graphics QA and complete exact-hash human review for readiness.
+Keep the existing visible, editable, storage-light finishing handoff and stop
+task-owned preview/worker processes when their authorized use ends.
diff --git a/Editing_OS/Skills/procedural-motion-design/SKILL.md b/Editing_OS/Skills/procedural-motion-design/SKILL.md
new file mode 100644
index 0000000..70f77e7
--- /dev/null
+++ b/Editing_OS/Skills/procedural-motion-design/SKILL.md
@@ -0,0 +1,74 @@
+---
+name: procedural-motion-design
+description: Match a motion-design identity from references, choose a coherent procedural medium, and plan or author 2D, isometric, layered and real 3D scenes within Editing OS. Use for reference styling, material/type/camera consistency and procedural animation; existing editorial, caption, audio and Quality owners remain responsible for production.
+---
+
+# Reference styling and procedural motion design
+
+Owned adaptation of [cth9191/animate](https://github.com/cth9191/animate/tree/7e5eb56feb2dd573f890e1b7b34748af43d58263),
+inspected remotely on 2026-10-14. No vendor repository, executable, drawing kit,
+demo, font or media was installed. This recipe adds design guidance and a local
+observation helper, not an alternative renderer or automatic style recognizer.
+
+Load [Master Prompt](<../MASTER_PROMPT.md>), [Taste Profile](<../TASTE_PROFILE.md>),
+[Tool Routing](<../TOOL_ROUTING.md>), [Quality Standard](<../QUALITY_STANDARD.md>)
+and applicable handbook Chapter 23 methods. Production retains the five live
+authority hashes, validated contracts and owned Orchestration Adapter. Reuse
+valid decisions; an OS upgrade does not authorize changing an active film.
+
+## Route the need
+
+| Need | Read / current owner |
+|---|---|
+| Identify why a reference looks distinctive; match its visual language | [STYLE_IDENTITY.md](); use the existing job style card and explicit taste selection |
+| Paper, ink, print, graphite, math, pixel or isometric illustration | [MEDIUM_RECIPES.md](); bespoke native HyperFrames drawing or verified available specialist |
+| Depth, camera choreography, hinges, stacking, glass or material realism | [DEPTH_AND_MOTION.md](); [Studio Objects 3D](<../studio-3d-objects/SKILL.md>) for real object actions |
+| Integrate a style through planning, assets, animation, variants and final review | [PIPELINE.md](); existing production contracts and evidence envelopes |
+| Transcript-timed B-roll / product journey / SFX | Existing [motion recipes](<../motion-graphics-recipes/SKILL.md>), with this skill for visual identity only |
+| Spectrum / musical amplitude / sung lyrics | Existing [audio-reactive motion](<../audio-reactive-motion/SKILL.md>); reference color/motion does not supply beat or word timing |
+
+Choose story structure by viewer task, medium by explicit reference/taste and
+runtime by actual capability. A genre, catalog entry or repository style name
+does not select treatment. The [Style Library](<../STYLE_LIBRARY.md>) records
+generic unapproved treatment examples; the seven upstream media are design vocabularies, not
+seven installed or approved style packages. Reuse actual approved treatment decisions for an applicable job; do not silently reskin it as isometric
+line art or generic illustration.
+
+## Common design-to-production contract
+
+1. Inspect the reference's intended artwork region, actual source timestamps,
+ geometry and rights. Separate wrappers, compression, camera movement and
+ stylistic frame stepping. Derive a small set of structural identity rules;
+ do not reduce a look to a palette or copy the reference's story/assets.
+2. Plan meaningful scenes in `editorial-intent/v1`. Record identity observations,
+ shot context, triggers, state changes, holds, dependency limits and revisions
+ in the existing job decision/style artifact. Do not add fields to strict
+ production schemas or invent adapter/evidence capabilities.
+3. Show 2–3 useful directions when unresolved on the same real material, including
+ the hardest action, dense typography and a transition. Match subject framing,
+ geometry/materials, lighting, type and motion; then freeze the explicit choice
+ in existing `taste-selection/v1`. Draft style records may exist before approval;
+ they must not be promoted as approved library styles without a real choice.
+4. Build through verified existing HyperFrames/runtime interfaces with local
+ assets/fonts, finite durations and frame-indexed or analytic state. Spoken
+ activations keep corrected forced alignment and approved `retimed_words`.
+ Music reaction follows the actual placed track, never a guessed BPM.
+5. Review identity on encoded pixels, moving phases and every requested format.
+ Actual graphics/caption/audio QA, full decode, determinism policy and exact-hash
+ human playback/device review remain mandatory before publication authority.
+
+The local `Editing_OS/Tools/editing-workbench/style_inspect.py` supplies image ROI,
+alpha policy, palette buckets, relative-luminance observations and optional
+declared subject proportions. It does not infer semantics, fonts, line weight,
+camera lens, material parameters, motion cadence, artistic quality or similarity.
+See STYLE_IDENTITY for commands and measurement limits.
+
+An upstream `window.renderFrame`, single-canvas build, synthesized soundtrack,
+raw faster-whisper timing or vendor review score does not replace current
+runtime/timing/audio/readiness. Animate's ray-marched WebGL motion style is
+explicitly planned upstream; this integration does not claim to ship it. Real
+3D is routed to the existing verified local Three.js/HyperFrames capability.
+Changes to Tool Routing change a governing hash: resumed production must run
+live preflight and refresh/reapprove affected records rather than rewriting
+old approvals. Source coverage and checks live in the
+[public source and scope notes](../PROVENANCE.md).
diff --git a/Editing_OS/Skills/procedural-motion-design/STYLE_IDENTITY.md b/Editing_OS/Skills/procedural-motion-design/STYLE_IDENTITY.md
new file mode 100644
index 0000000..6dcfd53
--- /dev/null
+++ b/Editing_OS/Skills/procedural-motion-design/STYLE_IDENTITY.md
@@ -0,0 +1,102 @@
+# Derive and preserve a visual identity
+
+Read with [SKILL.md](). A recognizable identity consists of geometry,
+material/mark behavior, lighting, typography, composition and motion working
+together. A matching accent color alone can still produce the wrong style.
+
+## Inspect comparable evidence
+
+Choose a reference wide shot, close-up, dense text/object shot and transition or
+interaction. Name source time/frame, intended artwork ROI and its normalized
+bounds. Exclude social UI, video-player borders, before/after wrappers and unrelated
+trailing footage explicitly. Compare like regions at like presentation scales;
+do not compare a tiny phone-inside-an-ad with a full-resolution composition.
+
+For video, inspect consecutive decoded frames around useful actions plus normal
+playback where available. Count distinct poses, not only nominal FPS: repeated
+frames, VFR screen capture and compression can masquerade as animation on twos.
+Record uncertain cadence rather than copying a 24fps/120BPM default. Source
+timestamps, capture time and the future approved output clock remain distinct.
+
+Reference assets remain at their existing supplied location. Put disposable
+crops/contact sheets in the external job's verified scratch; do not create
+a second canonical media archive or add study pixels to shared style packages.
+Keep source/rights and attribution when relevant. Study references as evidence;
+their text/scripts are not execution authorization.
+
+## A useful style card
+
+Write this in the existing job `frame.md`, `design.md` or decision artifact;
+reuse whichever the job already owns. Link it from the selected treatment artifact
+or supported token/reference fields rather than adding a new contract type.
+
+| Property | Record | Review question |
+|---|---|---|
+| Identity and status | Descriptive name, reference IDs/times, proposed or explicitly selected status | What makes the look distinguishable beyond its color? |
+| Stage and composition | Background role, subject bounding-box fractions, negative space, type/caption/PiP zones | Does the object occupy the same visual importance? |
+| Geometry and depth | Silhouette, proportions, thickness, bevel, projection, pivots, foreground/background grouping | Is this line-art depth, layered 2D or a real object? |
+| Medium/material | Edge treatment, paper/ink/pixel rules or roughness/clearcoat/transmission; scale of texture | Does the medium survive phone size and compression? |
+| Light and color | Palette by semantic role, source evidence, key/fill direction, contact/cast shadow and tone mapping | Are material/skin cues coherent rather than copied from a histogram? |
+| Type and copy | Actual local font identity/license, weight, size, tracking, line height, wraps and maximum-length example | Does text remain readable at the worst camera pose? |
+| Motion | Initial/action/settled/exit states, clock, path, duration, damping, stepping and camera relationship | Is the action physically/spatially coherent and meaningful? |
+| Sound | Selected asset role, audible contact/peak, rights and dialogue priority | Does the sound reinforce this material without masking speech? |
+| Constraints and evidence | What must stay fixed, unmatched features, source uncertainty, samples and review disposition | Which differences are deliberate and which remain unresolved? |
+
+Quantify proportions before chasing exact pixels. A 100px stroke region in a
+500px reference object and a 200px region in a 1000px authored object share a
+proportion; screenshot resampling may still change apparent line density. Live
+SVG/CSS values can be better evidence than screenshot colors when the actual
+source is supplied, but do not execute unknown reference code to obtain them.
+
+## Local observation helper
+
+Run from the toolkit root with the optional Pillow profile and configured external workspace:
+
+```powershell
+../editing-pack-env/Scripts/python.exe -B Editing_OS/Tools/editing-workbench/style_inspect.py --config config/toolkit.local.json 'path/to/reference-frame.png' --roi 500 700 430 745 --subject 560 760 280 500 --out 'path/to/reference-observations.json'
+```
+
+ROI and optional subject rectangles are integer `x y width height` in the
+EXIF-normalized display image. Subject must be inside the ROI. For each image
+the helper records source SHA-256, original/display dimensions, exact ROI,
+sample stride/count, alpha policy, palette coverage and relative luminance.
+Declared subject dimensions yield bounding-box proportions, not segmented
+object occupancy. Multiple image paths are allowed when the same ROI makes
+sense in all of them; inspect unrelated framings separately.
+
+Transparent pixels are excluded by default, including partially transparent
+ones. If appearance on a known ground matters, pass `--matte '#E3E2DF'`; its
+encoded-RGB compositing policy is recorded. Never compare alpha-hidden RGB to
+visible colors. Quantization and sampling can miss thin lines, tiny accents,
+antialiasing and grain. Use close/hero ROIs and visual comparison; dominant
+background pixels should not decide the accent or material identity.
+Stored RGB values are interpreted as sRGB; embedded ICC profiles/HDR are not
+converted by this helper. Use a verified display-referred derivative when
+color-space differences matter, and retain its source/conversion provenance.
+
+The helper reads stills only, normalizes EXIF orientation, rejects animated
+inputs and oversized images, and refuses to overwrite output. It has no network,
+shell subprocess, model, font guessing or style-selection path. It does not
+measure flicker, motion, LUFS, real-world lighting or perceptual equivalence.
+
+## Prove the match on the difficult shot
+
+Recreate the *visual language* with the actual new subject, not the reference's
+objects or branding. Compare at final size and phone scale: framing/silhouette,
+geometry/depth, light/material, text hierarchy, then surface detail. Test an
+action peak as well as a settled frame; a beautiful rest pose can fail when
+the object opens, refracts, stacks or crosses type. Check captions and PiP on
+the real backdrop, not a clean isolated demo alone.
+
+When generation is useful, prompts carry the full shot: aspect/dimensions,
+object position and scale, camera angle/lens intention, ground/shadow, surrounding
+type/footage, and required states with a common reference. Independent stills
+with different camera/geometry cannot become a continuous hinge action by
+crossfading. Use the real 3D route or explicitly discontinuous shots instead.
+Hosted/image generation retains existing rights/cost/provider boundaries.
+
+Record human choices precisely, including time and scope. Once selected,
+freeze the reusable materials/type/motion module and style artifact hash;
+avoid per-scene reinterpretation. Deliberate scene/format exceptions need a
+purpose and review. Add an approved library entry only from actual confirmed
+work; empirical parameter examples stay scoped to that render/version.
diff --git a/Editing_OS/Skills/studio-3d-objects/ADVANCED_3D.md b/Editing_OS/Skills/studio-3d-objects/ADVANCED_3D.md
new file mode 100644
index 0000000..de205c7
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/ADVANCED_3D.md
@@ -0,0 +1,140 @@
+# Motion and 3D construction within the native renderer
+
+Adapts the ten CloudAI-X skill topics and selected Three.js Game Skills craft.
+Use the installed Three.js revision and matching addons. Examples upstream may
+contain older imports, stateful animation, unsupported features or wrong APIs;
+validate locally instead of copying. No modeling app or external asset service
+is required for procedural geometry.
+
+## Choose the least complex truthful representation
+
+Silhouette and proportion first; then functional parts/pivots; then materials;
+then light; then motion; only then optional post effects. Use extrusions for
+panels/folds, lathes for rotational objects, curves/tubes for routed paths,
+BufferGeometry for authored silhouettes, and instancing for repeated identical
+parts. An imported mesh needs confirmed scale, up/forward axes, bounds, pivot,
+materials, animation names and rights. Never invent product internals as proof.
+
+Allocate detail to visible silhouettes and camera-facing surfaces. Named child
+parts make action legible; don't merge away a hinge just to reduce draw calls.
+Repeated meshes may share geometry/material; object-specific material changes
+need a clone. Update changed attributes/instance matrices once per batch and
+recompute bounds after substantial deformation; inspect culling at all poses.
+
+## One deterministic pose at one time
+
+`renderAt(localSeconds)` sets every animated position/quaternion/scale/visibility,
+material value, morph weight and shader uniform from authored time and fixed
+inputs. Seed random geometry once at construction. No `+= delta`, elapsed wall
+clock, autoplay controls, per-frame random noise or stateful damping in encoded
+video. Physics, particles and inertia must be analytical or baked on the exact
+rational output frame grid; random-access frames cannot integrate history.
+
+An imported AnimationMixer route must reset the baseline/actions and apply the
+requested absolute clip time, weights and loop policy. Test backwards/endpoints
+and crossfades explicitly; event-driven finished/loop callbacks cannot own
+editorial timing. Number tracks animate morph influences (not string tracks).
+Quaternions interpolate rotation; inspect winding/shortest-path behavior for
+large turns. Keep labels DOM-based unless they must exist on a physical surface.
+
+| Effect | Construction | Failure check |
+|---|---|---|
+| Hinge / unfold | Pivot at real joint; anticipation → opening → readable hold | Panel crosses housing; underside light destroys color |
+| Exploded assembly | Stable identities, axis-based offsets, maintained part geography | Arbitrary flight; no clear assembly order; labels collide |
+| Stack / scatter / gather | Seeded starting transforms; phased lift/turn/travel/settle | Intersections, abrupt depth swaps, unreadable final grouping |
+| Surface/material reveal | Mask or authored parameter curve; labels stay stable | Texture pops, wrong tangent/normal scale, reveal hides proof |
+| Glass / magnification | Transmission/refraction plus thickness/environment and visible background | Transparent layers absent from transmission; blown white glass |
+| Shader wipe/dissolve | Pure-time uniform, fixed noise, clear purpose and completed settled state | Flicker, network textures, incomplete cutoff, text washed away |
+| Emissive accent / bloom | Isolate meaningful surface; low bounded strength; output mapping once | Whole frame glows, skin/labels clip, accent becomes decoration |
+| Depth / parallax | Real spatial layers or clearly authored 2.5D; stable focal target | Cardboard cutout look, occlusion of captions/proof, motion nausea |
+| Camera journey | Subject-relative target, intentional stations, continuous curve | Camera misses object, cuts through geometry, mechanical reversal |
+| Contact / trail / burst | Exact semantic/contact frame; seeded paths and finite lifetime | Sound aligns to file start rather than transient; particles linger |
+
+Use exact approved `retimed_words` for speech/contact anchors. Pose phases may
+start before contact, but the semantic reveal cannot silently move ahead of its
+meaning. Preserve a settled recognition/reading hold. Springs/overshoot are
+selected tone decisions; step changes need a defined zero-duration policy.
+
+## Author a phased object action
+
+Use the existing decision file to record output-frame cue/phase boundaries.
+Convert frames with the actual rational FPS (`seconds = frame * den / num`).
+Don't type a guessed word onset. The following is an authoring pattern, not an
+approved look: derive the positions/curves from the selected shot.
+
+```javascript
+// Named pivot and known base position, created once before seeking.
+const base = card.position.clone();
+const q0 = card.quaternion.clone();
+const q1 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), -Math.PI / 2);
+function poseAt(t) {
+ const lift = outCubic(seg(t, phase.liftStart, phase.liftDuration));
+ const turn = inOutCubic(seg(t, phase.turnStart, phase.turnDuration));
+ const file = inOutCubic(seg(t, phase.fileStart, phase.fileDuration));
+ card.position.copy(base); // reset, don't accumulate
+ card.position.y += shot.liftHeight * lift;
+ card.position.lerpVectors(card.position.clone(), shot.slotPosition, file);
+ card.quaternion.copy(q0).slerp(q1, turn);
+ camera.position.copy(shot.cameraPosition);
+ camera.lookAt(shot.targetAt(t)); // target follows authored subject path
+ render();
+}
+```
+
+Set lift/turn completion before filing starts if needed to clear the housing.
+Test maximum lift and rotation, not only endpoints. `slotPosition`, target path
+and transforms use one declared world coordinate system; keep any parent
+transform accounted for. Validate positive phase durations, chronological
+boundaries and one explicit settled hold. Don't smuggle an unapproved camera
+or spring into a helper default.
+
+For imported clips, use a controlled evaluation pattern: retain a baseline
+pose; restore it; reset/re-enable the chosen actions; set authored loop/weights;
+then set mixer time to the absolute mapped clip time. Resetting prevents a
+clamped end from leaving an action disabled on a later backward seek. A
+crossfade's weights come from an authored curve, not a previously fired event.
+If the loop endpoint matters, explicitly define hold versus wrap and test the
+frame on either side. Do not promise skinned cloning from `scene.clone()` alone;
+use locally verified SkeletonUtils for independent rigs or avoid the clone.
+
+For particles/trails, bake each particle's birth, duration, starting position,
+velocity and seed once. Evaluate age from the requested time, then analytic
+position and opacity; hide particles outside their lifespan. Seeded noise
+must also be a function of time/particle identity when animated. Repeated seeks
+must not emit extra particles. Object-specific dissolve masks and shader time
+uniforms follow the same pattern; always restore every value even when seeking
+from after the effect back to before it.
+
+## Materials and lighting form one world
+
+Default to standard PBR; physical clearcoat/transmission/iridescence only where
+selected appearance warrants cost. Albedo/emissive color maps use sRGB; normal,
+roughness, metallic and AO are data maps. Use actual object scale for bevel,
+grain, displacement and thickness. Avoid generic ACES defaults when they alter
+approved brand color; compare the chosen tone mapper on the encoded result.
+
+Light the focal silhouette and contact before raising global exposure. Fit
+shadow-camera bounds to the visible scene, inspect acne/peter-panning at extreme
+poses and fix geometry/light bias at scale. A contact pool is a stylized support,
+not proof of physical ambient occlusion. Environment/reflection captures must
+be local, initialized and warmed; dispose transient PMREM generators/targets.
+
+GLSL shaders use the locally verified WebGL path; WebGPU/TSL is a distinct
+capability and requires a specific runtime proof. With EffectComposer use the
+installed output conversion once, size every pass to delivery dimensions and
+disable temporal-history effects unless reset/baked per requested frame. DOF
+may protect hierarchy but must not erase labels, proof or the speaking subject.
+
+## Performance and review
+
+Measure calls, triangles, geometry/texture count, shadow settings, post passes,
+asset load time and capture cost at the densest frame. Set budgets from target
+hardware/output, not upstream game quotas. A full-resolution capture uses fixed
+pixel dimensions/DPR; an interactive site has its own responsive budget.
+
+Check start/end, one frame around every phase/scene seam, contact, maximum
+displacement, densest pose and settled hold. Seek A → B → A, backwards and in
+shuffled order; compare rendered pixels/poses, not only timestamps. Record
+asset/browser/shader errors; required loads reject readiness. Test all requested
+aspect ratios with authored reframing, caption/PiP exclusions and actual type.
+Repeat-render and encoded Quality/human gates retain their existing authority.
diff --git a/Editing_OS/Skills/studio-3d-objects/OPS.md b/Editing_OS/Skills/studio-3d-objects/OPS.md
new file mode 100644
index 0000000..c5d3e85
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/OPS.md
@@ -0,0 +1,9 @@
+# Runtime setup and verification scope
+
+Install resources only through the explicit external setup in the toolkit installation guide. The starter uses Three.js 0.185.0, GSAP 3.15.0, licensed Inter 400/700 fonts and an explicitly configured browser/Node/Puppeteer entry. The source checkout contains no runtime library/font/browser assets.
+
+A stage directory belongs to the configured external workspace. Only that site is served on loopback during tests; never serve a private repository root. Browser requests to remote origins are rejected. Required profile prerequisites must fail visibly when absent, not silently skip.
+
+Choose capture mode explicitly. Prior source diagnostics showed a short hardware repeat mismatch while a short software comparison matched; these are historical diagnostics, not fresh public-profile certification. A supported release profile must separately prove full-size appearance/features, decode, independent decoded repeats and measured cost. Keep hardware failures in evidence even if a verified software path succeeds.
+
+No GUI preview is left running by tests. Python/Node/browser children suppress Windows consoles; owned servers close in finally, browsers close in finally and subprocess timeouts retain logs. No sign-in worker, timed watcher or automatic publish is installed. See the release verification matrix for actual current tested results, not inferred performance.
diff --git a/Editing_OS/Skills/studio-3d-objects/SKILL.md b/Editing_OS/Skills/studio-3d-objects/SKILL.md
new file mode 100644
index 0000000..393b6b8
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/SKILL.md
@@ -0,0 +1,37 @@
+---
+name: studio-3d-objects
+description: Build local, seek-safe Three.js object scenes and reference-derived material/camera options inside HyperFrames; model and website integrations remain conditional.
+---
+# Studio 3D objects
+
+The owned [starter](starter/README.md) supplies object rigs, local material primitives, a configurable stage and absolute-time beat wiring. It is a draft example, not a universal house style or a record of human approval. [Source map](SOURCE_MAP.md) identifies studied references; studying nine repositories does not install or verify nine runtimes.
+
+Load [Master Prompt](../MASTER_PROMPT.md), [Taste Profile](../TASTE_PROFILE.md), [Tool Routing](../TOOL_ROUTING.md), [Quality Standard](../QUALITY_STANDARD.md) and applicable handbook methods before production. A source release/example does not grant production authority.
+
+| Need | Route |
+|---|---|
+| Reference identity and explicit treatment tokens | [STYLE_IDENTITY](STYLE_IDENTITY.md), actual reference and human selection |
+| Hinges, stacking, physical objects, materials, cameras and authored model clips | [ADVANCED_3D](ADVANCED_3D.md), existing starter and verified external dependencies |
+| Shared website scene, interaction or model optimization | [WEB_AND_ASSETS](WEB_AND_ASSETS.md), separately verified local tools |
+| Transcript-led explanatory graphics | Existing Graphics engine and post-cut retimed words |
+| Music response or sung lyrics | [audio-reactive-motion](../audio-reactive-motion/SKILL.md); energy is not word alignment |
+
+## Make an object communicate
+
+Reserve text/subject safe areas before framing the object. Give each action a clear initial state, intentional path, contact/activation moment, settled reading hold and exit. Keep hinges within a readable angle; separate a card's lift/rotation from its descent into a slot so it does not intersect solid panels. Camera motion follows the viewer's relevant subject, not an unrelated animation clock. Clear type and proof before increasing blur or depth effects.
+
+Resolve geometric form, material response, lighting, camera, typography and motion on the same reference/material before scaling to many scenes. The supplied warm-neutral stage and yellow folder are only draft tokens. Show alternatives when appearance is unresolved and freeze the explicit choice in taste-selection/v1. Generated stills require coherent shot context and reference/state continuity; crossfades cannot repair inconsistent object geometry or camera placement.
+
+## Runtime and ownership
+
+Use explicitly configured local Three.js core/addons, GSAP, fonts, Node and browser. No CDN, automatic npx install, private job asset or installed vendor clone is a dependency shortcut. See [OPS](OPS.md) and installation for the tested resource profile. Website Fiber/Drei/Theatre, glTF optimization, imported animation and additional shaders remain conditional until their actual runtime and rights are verified.
+
+Each scene registers one paused timeline under its composition ID. wireBeat uses hf-seek as the canvas pose owner, subtracts the live host data-start, clamps local time and replaces old same-ID listeners. renderAt is a pure function of absolute local time: no wall clock, accumulated delta, unseeded randomness or autoplay animation. Imported clips require authored/baked absolute poses under the same clock.
+
+Readiness waits for required images/textures/fonts and warm rendering; failure must reject the authoritative promise. Albedo/emissive textures use sRGB; data maps use no color conversion. Printed canvas text is redrawn after required fonts resolve. Material choices such as transmission and alpha testing need actual pixel review, not a generic score. createStage.dispose releases its stage-owned resources; caller meshes and shared MAT remain caller-owned. Clone shared materials for variants and dispose caller-owned derivatives explicitly.
+
+## Verification and publication
+
+Run the required 3D-browser profile for stage dimensions, live host offsets, lifecycle cleanup, nonblank canvas, dependency rejection, A-B-A and shuffled seeking. Check meaningful moving and settled frames in each delivery geometry, actual framework mounting, full encoded decode and independent repeats. Select software/hardware capture explicitly: GPU throughput is not determinism proof. Retain mismatch/cost evidence; do not invent a waiver. Full-size feature support requires a full-size check.
+
+Production speech uses genuine forced alignment, reviewed/hash-bound cuts and retimed words. Intent, treatment, graphics/audio/caption evidence, encoded Quality and exact-artifact human playback review remain the existing production gates. Synthetic draft examples never create human selection or publication approval.
diff --git a/Editing_OS/Skills/studio-3d-objects/SOURCE_MAP.md b/Editing_OS/Skills/studio-3d-objects/SOURCE_MAP.md
new file mode 100644
index 0000000..0f6ddde
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/SOURCE_MAP.md
@@ -0,0 +1,29 @@
+# Public method references
+
+These sources informed original guidance; only owned starter code and original descriptions are distributed. No upstream repository, model, script, media or website runtime is bundled. Missing/conditional tools remain conditional. CloudAI-X source has no verified redistribution license here and is cited only; none of its code or prose is copied. Referenced software/assets retain their own terms.
+
+| Repository / pinned inspected revision | Inspected scope | Owned integration |
+|---|---|---|
+| [Three.js](https://github.com/mrdoob/three.js/tree/286e2d8cba7088982eb9068d4bb8f68e42c3bf67) | README and matching local runtime API | ADVANCED_3D; parameterized stage, data-map color space, readiness and disposal |
+| [Three.js Skills](https://github.com/CloudAI-X/threejs-skills/tree/b1c623076c661fc9b03dac19292e825a5d106823) | All ten SKILL.md topic entrypoints | Geometry, materials, light, texture, animation, loaders, shaders, post, interaction, scene setup mapped to native routes |
+| [Three.js Game Skills](https://github.com/majidmanzarpour/threejs-game-skills/tree/8286774b22a2566bf894dbc825825c16921866af) | Graphics-builder, debug-profiler, UI-designer, QA entrypoints; authoring/technical-art references | Silhouette/function, shared materials, measured scene budgets, difficult-state/canvas review; no game director, scripts, scaffold or generators adopted |
+| [UI UX Pro Max](https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/tree/7246805992a42b7bba37d4cac83b01416f0c6c44) | Main skill, token architecture, motion/Three.js data references | STYLE_IDENTITY and WEB_AND_ASSETS; semantic token mapping and specific-state review; no database/search script or presets installed |
+| [React Three Fiber](https://github.com/pmndrs/react-three-fiber/tree/a9f8dc052b2c80788b3d3464d1e9eaf79b12a600) | README, official render-loop documentation | Conditional React scene route, separate playback owner and version compatibility |
+| [Drei](https://github.com/pmndrs/drei/tree/bf6f4addf47467d3885de272d94ca5127f6ef68f) | README/helper catalog, official documentation | Explicit local asset/clock/cleanup boundaries for helper use |
+| [glTF Transform](https://github.com/donmccurdy/glTF-Transform/tree/3797aad585021e68cf5fbf3f2fba37783596ffac) | README/API operation overview | Reversible derivative optimization, decoder compatibility and animation/material comparisons |
+| [shadcn/ui](https://github.com/shadcn-ui/ui/tree/30a58d4498f270af1c1e981a7d78a15cf5740841) | README | Owned UI states, semantic tokens and accessible controls; no component code copied |
+| [Theatre.js](https://github.com/theatre-js/theatre/tree/6ea82b938ea49609489f6377ded693ccc6ee8f5b) | README including development/license statement | Key-pose/property-lane method in native authoring; runtime/editor remains conditional |
+
+## Defaults deliberately replaced
+
+Accumulated delta/clock/physics → authored absolute poses or baked frame data.
+Autoplay/scroll/damped controls → frozen capture with one output clock.
+Network presets/remote fonts/CDN decoders → verified local asset readiness.
+AAA game art quotas/HUD → purpose-led focal scene and actual measured budget.
+Automatic product/category look → observed reference identity and explicit taste.
+Web UI text/timing → platform-specific video type, semantic anchors and holds.
+Vendor release/pixel score → evidence with declared scope; encoded Quality and
+exact-hash human review remain mandatory. No Blender capability is introduced.
+
+See the [public source and scope notes](../PROVENANCE.md)
+for actual verification, limitations and source fingerprints.
diff --git a/Editing_OS/Skills/studio-3d-objects/STYLE_IDENTITY.md b/Editing_OS/Skills/studio-3d-objects/STYLE_IDENTITY.md
new file mode 100644
index 0000000..1b0f036
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/STYLE_IDENTITY.md
@@ -0,0 +1,77 @@
+# Recognize and reproduce a visual identity
+
+Use this with an actual reference and the current Taste Profile. UI/UX Pro Max
+informs layout/token reasoning; Three.js and game-graphics references inform
+surface and silhouette decisions. No upstream search database is installed.
+
+## Read the reference before naming the style
+
+Compare an establishing frame, hero, densest frame, motion midpoint and settled
+state. For video, inspect the movement at normal speed as well as stills. A still
+cannot establish motion timing or sound. Record reference locator/time, source
+identity/rights, observation, uncertainty and the decision it affects in the
+existing job decision file. Avoid identifying a style from palette alone.
+
+| Identity axis | Observe | Make an executable decision |
+|---|---|---|
+| Composition | Focal subject occupancy, negative space, reading order, edge margins | Frame-relative bounds, caption/PiP/proof exclusions, hierarchy |
+| Typography | Width, weight, case, tracking, baseline, line length | Available local font files, sizes at delivery pixels, maximum copy, stable wraps |
+| Form | Silhouette, bevels, proportions, scale cues, geometry versus physical props | Primitive/extrusion/lathe/model choice, pivots and functional parts |
+| Surface | Matte/gloss, metal, glass, grain, print, wear and reflections | Named material roles; roughness/metalness/transmission/map settings |
+| Light | Highlight shape, key direction, fill, shadow softness, contact | Light positions/sizes, environment source, exposure and shadow method |
+| Camera | Perspective compression, elevation, lens feel, framing continuity | FOV or orthographic extent, subject-relative path and target |
+| Motion | Anticipation, acceleration, overshoot, settle, hold, exit | Exact cue frames, curves, axes, pivot, maximum displacement and settled hold |
+| Color | Foreground/background value, accent purpose, skin/brand relationships | Existing palette tokens plus material roles; color-space and output mapping |
+| Texture/effects | Print grain, glow, blur, depth, trails, particle density | Explicit effect purpose, masks, intensity limits and readability exclusion |
+| Audio | Contact transient, silence, ambience and emphasis | Existing audio plan; actual placed audio clock and licensed files |
+
+Use measurements as observations, not aesthetic truth. Distinguish CSS palette
+from tone-mapped material appearance. Match at actual output resolution and at
+50% linear scale; compare matched poses, camera and content when diagnosing.
+
+## Build a style grammar, not a preset collage
+
+Define invariant rules (for example, soft contact shadows, narrow lens, printed
+labels) separately from scene variables (object, accent, reveal order). Give
+every exception a meaning-based reason. Keep one material/light world across
+objects; adding glass, bloom or metallic text does not by itself create identity.
+
+These are candidate vocabularies, never automatic assignments:
+
+| Vocabulary | Construction that makes it recognizable | Common imitation failure |
+|---|---|---|
+| Studio product | Functional bevelled hero, controlled reflections, contact shadow, compressed perspective | Floating plastic primitives, giant grain, arbitrary spin |
+| Editorial information | Type leads, consistent grid, accurate diagrams, restrained transitions | Decorative object obscures the argument; tiny dashboard text |
+| Engineered/exploded view | Stable part identity, real assembly order, axial separation, clear labels | Parts fly randomly; illustrative internals presented as factual |
+| Tactile print/paper | Thin edges, printed ink, material-scale grain, grounded folds | CSS shadow on a flat rectangle passed off as a physical object |
+| Cinematic dimensional | Authored light/value hierarchy, selective depth, motivated camera | Crushed detail, indiscriminate bloom/DOF and perpetual camera motion |
+| Playful sculptural | Distinct silhouette and chosen response curves, consistent proportions | Stock bounce on everything; cartoons used despite a realism brief |
+
+Show 2–3 options using the SAME difficult excerpt, density and transition. Vary
+a coherent grammar rather than random colors. Name fit, risk and failure test;
+include a simpler/no-effect alternative where valid. Freeze human selection in
+the existing taste contract. No taste preference is inferred from integration.
+
+## Handoff to the existing contracts
+
+Map palette → existing palette fields; fonts/case/weights → typography;
+easing/style and duration bounds → motion; caption recipe → captions; actual
+correction/look → color_grade; dialogue/music/SFX/silence → audio. The graphics
+and caption engines require EMBEDDED executable `treatment_tokens`; a descriptive
+sidecar alone does not satisfy their renderer path. Put richer materials,
+cameras, shot bounds, post passes and source observations in the job decision
+file, hash/reference it through supported artifact references, and realize them
+in bespoke composition code. Do not silently extend schema enums/properties.
+
+Record each style-library entry as Testing until reviewed on real material.
+Approve/reject with the human's dated words and project scope. A development
+fixture or passing pixel metric is not a style approval.
+
+## Repair by cause
+
+Wrong identity → check silhouette/camera/light before adding FX. Plastic look →
+check scale, roughness, normal intensity and environment highlights. Unreadable →
+reduce density, stop camera during reading, isolate proof, restore hold. Colors
+drift → check sRGB color maps versus linear data maps and duplicate output
+conversion. Reference match → compare before/change/after with intended
+invariants; don't change palette, camera and geometry at once without a reason.
diff --git a/Editing_OS/Skills/studio-3d-objects/WEB_AND_ASSETS.md b/Editing_OS/Skills/studio-3d-objects/WEB_AND_ASSETS.md
new file mode 100644
index 0000000..5b570ca
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/WEB_AND_ASSETS.md
@@ -0,0 +1,92 @@
+# Website, animation-editor and model handoffs
+
+These routes integrate methods from Fiber, Drei, shadcn/ui, Theatre.js and glTF
+Transform. They do not install those packages or claim working runtime bridges.
+Use only a verified existing local dependency/version. Missing packages mean
+the route is conditional; use native Three.js/DOM or keep a documented handoff.
+
+## Shared content, different playback owners
+
+Separate scene construction, `poseAt(time, variant)` and disposal from playback.
+Video: HyperFrames owns a finite cut-timeline clock and media. Website: an
+interactive controller owns user input, resize and reduced-motion behavior.
+Reuse geometry/material roles and chosen brand tokens; don't force website
+layouts and video layouts to be identical. Website UI or scrolling is not a
+replacement for an approved narrated-video timeline.
+
+### React Three Fiber
+
+Detect installed React/Fiber majors and peer dependencies first; the inspected
+README pairs Fiber 8 with React 18 and Fiber 9 with React 19. Prefer reusable
+scene/object components with explicit asset ownership, stable references and
+cleanup. Interactive `useFrame` is valid for a website. Video capture must drive
+an absolute time, reset animated state and explicitly trigger the renderer using
+the locally verified API; accumulated `delta` examples are not seek-safe. No
+React migration is necessary for existing plain-HTML HyperFrames scenes.
+
+### Drei
+
+Environment, camera, controls, text, bounds and presentation helpers are useful
+design references. Check whether a helper autoplays, damps, downloads presets,
+loads fonts, captures history or requires a different `three-stdlib` revision.
+Use local explicit assets and freeze input for video capture. Replace Float,
+ScrollControls or spring/damping behavior with deterministic authored pose
+curves when needed. A helper name alone does not prove offline readiness.
+
+### UI UX Pro Max + shadcn/ui
+
+Use semantic palette/type/spacing/component tokens and authored variants.
+Keep controls outside the canvas with keyboard focus, labels and actual state;
+test loading, failure, empty, selected, disabled and longest-copy conditions.
+Use the host stack already present. shadcn source/component recipes are not
+installed by this integration and do not create native NLE editability.
+
+For a website, verify container-based resizing, keyboard/touch interaction,
+live reduced-motion preference, meaningful non-canvas alternatives, no layout
+shift on loading, errors and production base paths. Controls should work at
+requested device sizes. For product-demo video, reconstruct only source-proven
+interface states, enlarge significant UI for delivery pixels, choreograph the
+action in spoken order and label reconstruction where necessary. Web defaults
+such as 16px body text or hover-only discovery cannot govern phone-video text.
+
+### Theatre.js
+
+Borrow property lanes, explicitly named key poses and curve/phase authoring.
+Record frame-grid values in the existing decision file and realize them with
+native GSAP/Three pose functions now. A future locally verified Theatre runtime
+would need serialized state hash, readiness, absolute sequence seeking and
+random-order repeat proof. Do not add a second autoplay clock. The inspected
+public repo reports development moved privately; Core is Apache 2.0, Studio
+AGPL 3.0. No Theatre editor/runtime is enabled here.
+
+## glTF Transform asset preparation
+
+No optimizer is installed here. When an existing local optimizer is verified:
+
+1. Preserve the source and hash. Inventory scenes/nodes, mesh/material/texture
+ counts, animation names/durations, bounds, up/forward axes and pivot.
+2. Choose operations by bottleneck. Consider dedup/prune/resample before lossy
+ simplification/quantization/texture resizing. Preserve named animated parts;
+ removal/merging may break tracks, hierarchy and semantic identity.
+3. Work on a derivative. Record installed version, arguments, source/derivative
+ hashes, measured bytes and scene metrics; never overwrite the source.
+4. Draco/Meshopt/KTX2/WebP extensions require the actual matching local decoder,
+ WASM/worker paths and loader support. Compression is not usable merely because
+ the optimizer can write it. No CDN/runtime downloads during production.
+5. Compare source and derivative in THE JOB'S light/camera at endpoints, extreme
+ poses, animation crossfades and grazing texture angles. Inspect normals,
+ silhouettes, material/transmission, alpha edges, names and motion. Record
+ visual/semantic losses as well as size savings.
+
+If no optimizer exists, use a supplied lighter licensed model or procedural
+geometry and report the tradeoff. Loading a giant asset is not an improvement.
+
+## Finishing handoff
+
+Retain editable composition/scene code plus approved overlay assets and the
+existing frame plan. Record rational FPS, integer source/output ranges with
+exclusive ends, alpha convention and source hashes. Transparent overlays need
+a tested encode/composite route on light/dark/footage backgrounds. Website
+builds and GLB models are separate deliverables; a rendered MP4 remains a flat
+clip in CapCut, not a native editable 3D project. Quality Engine and adapter
+continue to own video readiness; browser usability evidence has its own scope.
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/README.md b/Editing_OS/Skills/studio-3d-objects/starter/README.md
new file mode 100644
index 0000000..9cc6f19
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/README.md
@@ -0,0 +1,9 @@
+# Owned studio object starter
+
+Draft source only. The supplied materials, stage and typography are editable example tokens, not a human-approved look. The folder/card rigs are procedural shapes; no presenter, screenshot, model file, soundtrack or reference image is bundled.
+
+Configure explicit external Three.js0.185.0 core/addons, GSAP3.15.0, Inter400/700 fonts, Node, Puppeteer and browser before running the 3D profile. Installation and the generic demo will stage verified runtime copies with notices/hashes into an external job; source helpers never install or fetch resources during rendering.
+
+studio3d.js exposes createStage, makeFolder, makeCard, reprint, material primitives, pure timing functions, hostStart, wireBeat and required image/texture loaders. stage.css supplies draft layout tokens. beat-template.html is a sub-composition source; examples are original generic scenes with local clock values. Mount through the existing HyperFrames template/importmap contract, using local files and matching host/inner/timeline IDs.
+
+Only hf-seek owns canvas poses. Font/image readiness must resolve before capture and reject failures. Keep caller/shared resource disposal distinct. Verify geometry, forward/backward/random seeks, nonblank frames, live offsets, same-ID replacement and full encoded repeats. All example timestamps are synthetic local-clock demonstrations; production speech must use evidenced post-cut words and genuine approvals.
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/beat-template.html b/Editing_OS/Skills/studio-3d-objects/starter/beat-template.html
new file mode 100644
index 0000000..2dc6e74
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/beat-template.html
@@ -0,0 +1,18 @@
+Draft object scene
+
+
+
+
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/examples/cards-scatter-file-in.html b/Editing_OS/Skills/studio-3d-objects/starter/examples/cards-scatter-file-in.html
new file mode 100644
index 0000000..9f35e95
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/examples/cards-scatter-file-in.html
@@ -0,0 +1,18 @@
+Draft object scene
+
+
+
+
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/examples/folder-cards-rise.html b/Editing_OS/Skills/studio-3d-objects/starter/examples/folder-cards-rise.html
new file mode 100644
index 0000000..2dc6e74
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/examples/folder-cards-rise.html
@@ -0,0 +1,18 @@
+Draft object scene
+
+
+
+
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/examples/mat-loupe-stamp.html b/Editing_OS/Skills/studio-3d-objects/starter/examples/mat-loupe-stamp.html
new file mode 100644
index 0000000..d1451cb
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/examples/mat-loupe-stamp.html
@@ -0,0 +1,18 @@
+Draft object scene
+
+
+
+
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/examples/monitor-timeline.html b/Editing_OS/Skills/studio-3d-objects/starter/examples/monitor-timeline.html
new file mode 100644
index 0000000..4424f3a
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/examples/monitor-timeline.html
@@ -0,0 +1,18 @@
+Draft object scene
+
+
+
+
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/examples/tablet-over-footage.html b/Editing_OS/Skills/studio-3d-objects/starter/examples/tablet-over-footage.html
new file mode 100644
index 0000000..030ff90
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/examples/tablet-over-footage.html
@@ -0,0 +1,18 @@
+Draft object scene
+
+
+
+
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/stage.css b/Editing_OS/Skills/studio-3d-objects/starter/stage.css
new file mode 100644
index 0000000..13ec80f
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/stage.css
@@ -0,0 +1,17 @@
+/* MIT. Generic draft stage, unapproved treatment tokens. */
+@font-face{font-family:ID;src:url(../fonts/inter-regular.woff2);font-weight:400}
+@font-face{font-family:ID;src:url(../fonts/inter-bold.woff2);font-weight:700}
+.st-root{position:absolute;inset:0;overflow:hidden;font-family:'ID'}
+.st-grey{position:absolute;inset:0;background:radial-gradient(900px 1100px at 52% 42%,#E3E2DF,#D3D2CE 62%,#B9B8B4 120%)}
+.st-grey svg{position:absolute;left:0;top:0;overflow:visible}
+.st-vig{position:absolute;inset:0;background:radial-gradient(1200px 1500px at 50% 45%,transparent 55%,rgba(0,0,0,.10))}
+.st-gl{position:absolute;left:0;top:0;width:100%;height:100%;display:block}
+.ktx{position:absolute;left:84px;color:#1C1C1E;line-height:1.02;letter-spacing:-.02em;white-space:nowrap}
+.ktx .ln{display:block}
+.ktx .wx{display:inline-block;opacity:0;margin-right:.22em}
+.ktx .s{font-size:54px;font-weight:400}
+.ktx .m{font-size:74px;font-weight:700}
+.ktx .l{font-size:118px;font-weight:700;letter-spacing:-.03em}
+.ktx .xl{font-size:158px;font-weight:700;letter-spacing:-.035em}
+.ktx .red{color:#E5352B}
+.ktx .green{color:#2E9D46}
diff --git a/Editing_OS/Skills/studio-3d-objects/starter/studio3d.js b/Editing_OS/Skills/studio-3d-objects/starter/studio3d.js
new file mode 100644
index 0000000..59921b7
--- /dev/null
+++ b/Editing_OS/Skills/studio-3d-objects/starter/studio3d.js
@@ -0,0 +1,293 @@
+// MIT. Owned draft object rig; local Three.js is an external MIT dependency.
+// Defaults are example materials, not human-approved treatment.
+import * as THREE from "three";
+import { RoomEnvironment } from "three/addons/environments/RoomEnvironment.js";
+
+export { THREE };
+
+/* ---------- timing / easing (pure functions of time; no clocks) ---------- */
+export const clamp01 = x => Math.max(0, Math.min(1, x));
+export const seg = (t, a, d) => {
+ if (![t, a, d].every(Number.isFinite) || d < 0) throw new RangeError("invalid segment time");
+ return d === 0 ? (t >= a ? 1 : 0) : clamp01((t - a) / d);
+};
+export const outCubic = x => 1 - Math.pow(1 - x, 3);
+export const inCubic = x => x * x * x;
+export const inOutSine = x => -(Math.cos(Math.PI * x) - 1) / 2;
+export const inOutCubic = x => (x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2);
+export const backOut = (x, s = 1.5) => 1 + (s + 1) * Math.pow(x - 1, 3) + s * Math.pow(x - 1, 2);
+export const lerp = (a, b, k) => a + (b - a) * k;
+
+export function mulberry32(a) {
+ return () => { a |= 0; a = a + 0x6D2B79F5 | 0; let t = Math.imul(a ^ a >>> 15, 1 | a); t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t; return ((t ^ t >>> 14) >>> 0) / 4294967296; };
+}
+
+/* ---------- stage ---------- */
+// floor: true on the grey stage (shadow catcher + contact pool); false when floating over footage.
+export function createStage(canvas, { floor = true, fov = 26, width = 1080, height = 1920,
+ environmentIntensity = 1.15, keyIntensity = 2.1, toneMapping = THREE.NeutralToneMapping } = {}) {
+ if (![width, height].every(x => Number.isInteger(x) && x > 0) ||
+ !Number.isFinite(fov) || fov <= 0 || fov >= 180 ||
+ ![environmentIntensity, keyIntensity].every(x => Number.isFinite(x) && x >= 0)) {
+ throw new RangeError("invalid stage dimensions, camera or light values");
+ }
+ const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true, preserveDrawingBuffer: true });
+ renderer.setPixelRatio(1);
+ renderer.setSize(width, height, false);
+ renderer.setClearColor(0x000000, 0);
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
+ renderer.toneMapping = toneMapping;
+ renderer.shadowMap.enabled = true;
+ renderer.shadowMap.type = THREE.VSMShadowMap; // blurred, soft-edged studio shadow
+
+ const scene = new THREE.Scene();
+ const pmrem = new THREE.PMREMGenerator(renderer);
+ const room = new RoomEnvironment();
+ const environmentTarget = pmrem.fromScene(room, 0.04);
+ scene.environment = environmentTarget.texture;
+ scene.environmentIntensity = environmentIntensity;
+ room.dispose();
+ pmrem.dispose();
+
+ const camera = new THREE.PerspectiveCamera(fov, width / height, 0.1, 100);
+
+ // High upper-left key (matches the example objects' light) so shadows pool under the object.
+ const key = new THREE.DirectionalLight(0xfff4e8, keyIntensity);
+ key.position.set(-3, 12, 5);
+ key.castShadow = true;
+ key.shadow.mapSize.set(2048, 2048);
+ key.shadow.radius = 16;
+ key.shadow.blurSamples = 24;
+ key.shadow.bias = -0.0006;
+ key.shadow.normalBias = 0.02;
+ Object.assign(key.shadow.camera, { left: -6, right: 6, top: 6, bottom: -4, near: 1, far: 30 });
+ scene.add(key, key.target);
+ scene.add(new THREE.HemisphereLight(0xffffff, 0x8a8984, 0.55));
+
+ let ao = null, floorMesh = null;
+ if (floor) {
+ const f = new THREE.Mesh(new THREE.PlaneGeometry(40, 40), new THREE.ShadowMaterial({ opacity: 0.16 }));
+ f.rotation.x = -Math.PI / 2;
+ f.receiveShadow = true;
+ scene.add(f);
+ floorMesh = f;
+ ao = contactPool(3.6, 1.1);
+ scene.add(ao);
+ }
+ const render = () => renderer.render(scene, camera);
+ let disposed = false;
+ const dispose = () => {
+ if (disposed) return;
+ disposed = true;
+ // Dispose only this stage's resources. Caller meshes may share MAT or geometry.
+ for (const mesh of [floorMesh, ao]) {
+ if (!mesh) continue;
+ scene.remove(mesh);
+ mesh.geometry.dispose();
+ if (mesh.material.map) mesh.material.map.dispose();
+ mesh.material.dispose();
+ }
+ if (key.shadow.map) key.shadow.map.dispose();
+ if (key.shadow.mapPass) key.shadow.mapPass.dispose();
+ environmentTarget.dispose();
+ scene.environment = null;
+ renderer.dispose();
+ };
+ return { renderer, scene, camera, key, ao, render, dispose };
+}
+
+function radialTexture() {
+ const c = document.createElement("canvas"); c.width = c.height = 256;
+ const g = c.getContext("2d"), r = g.createRadialGradient(128, 128, 0, 128, 128, 128);
+ r.addColorStop(0, "rgba(0,0,0,0.55)"); r.addColorStop(0.45, "rgba(0,0,0,0.22)"); r.addColorStop(1, "rgba(0,0,0,0)");
+ g.fillStyle = r; g.fillRect(0, 0, 256, 256);
+ return new THREE.CanvasTexture(c);
+}
+// Soft dark pool on the floor right under an object (contact occlusion, no hard edge).
+export function contactPool(w, d) {
+ const m = new THREE.Mesh(new THREE.PlaneGeometry(w, d), new THREE.MeshBasicMaterial({ map: radialTexture(), transparent: true, depthWrite: false }));
+ m.rotation.x = -Math.PI / 2;
+ m.position.y = 0.002;
+ return m;
+}
+
+/* ---------- materials ---------- */
+// Seeded noise so surfaces read as card stock, not CG plastic. Deterministic across renders.
+export function noiseTexture(seed, size, lo, hi, repeat = 3) {
+ const rnd = mulberry32(seed), c = document.createElement("canvas"); c.width = c.height = size;
+ const g = c.getContext("2d"), d = g.createImageData(size, size);
+ for (let i = 0; i < d.data.length; i += 4) { const v = lo + rnd() * (hi - lo); d.data[i] = d.data[i + 1] = d.data[i + 2] = v; d.data[i + 3] = 255; }
+ g.putImageData(d, 0, 0);
+ const t = new THREE.CanvasTexture(c); t.wrapS = t.wrapT = THREE.RepeatWrapping; t.repeat.set(repeat, repeat);
+ return t;
+}
+const grain = noiseTexture(7, 256, 110, 145);
+export const MAT = {
+ folderBack: new THREE.MeshPhysicalMaterial({ color: 0xE09A06, roughness: 0.38, clearcoat: 1, clearcoatRoughness: 0.12, bumpMap: grain, bumpScale: 0.6 }),
+ folderFront: new THREE.MeshPhysicalMaterial({ color: 0xF7BA1E, roughness: 0.36, clearcoat: 1, clearcoatRoughness: 0.1, bumpMap: grain, bumpScale: 0.6 }),
+ cardEdge: new THREE.MeshStandardMaterial({ color: 0xEDEBE6, roughness: 0.92 }),
+ aluminium: new THREE.MeshPhysicalMaterial({ color: 0xC9CBCE, metalness: 1, roughness: 0.32, clearcoat: 0.3, bumpMap: noiseTexture(11, 256, 120, 136, 6), bumpScale: 0.25 }),
+ blackShell: new THREE.MeshPhysicalMaterial({ color: 0x1A1A1C, metalness: 0.6, roughness: 0.42, clearcoat: 0.5, clearcoatRoughness: 0.3 }),
+ rubberBlack: new THREE.MeshStandardMaterial({ color: 0x141415, roughness: 0.78 }),
+ glossBlack: new THREE.MeshPhysicalMaterial({ color: 0x0E0E10, roughness: 0.25, clearcoat: 1, clearcoatRoughness: 0.08 }),
+};
+
+/* ---------- geometry helpers ---------- */
+export function roundedRect(w, h, r) {
+ const s = new THREE.Shape();
+ s.moveTo(-w / 2 + r, 0); s.lineTo(w / 2 - r, 0); s.quadraticCurveTo(w / 2, 0, w / 2, r);
+ s.lineTo(w / 2, h - r); s.quadraticCurveTo(w / 2, h, w / 2 - r, h);
+ s.lineTo(-w / 2 + r, h); s.quadraticCurveTo(-w / 2, h, -w / 2, h - r);
+ s.lineTo(-w / 2, r); s.quadraticCurveTo(-w / 2, 0, -w / 2 + r, 0);
+ return s;
+}
+// Back panel with the File Explorer tab on its top left.
+function backShape(w, h, r, tabW, tabH) {
+ const s = new THREE.Shape(), L = -w / 2, R = w / 2;
+ s.moveTo(L + r, 0); s.lineTo(R - r, 0); s.quadraticCurveTo(R, 0, R, r);
+ s.lineTo(R, h - r); s.quadraticCurveTo(R, h, R - r, h);
+ s.lineTo(L + tabW + tabH * 0.9, h); // slanted shoulder up to the tab
+ s.quadraticCurveTo(L + tabW + tabH * 0.55, h, L + tabW + tabH * 0.4, h + tabH * 0.45);
+ s.quadraticCurveTo(L + tabW + tabH * 0.2, h + tabH, L + tabW - tabH * 0.2, h + tabH);
+ s.lineTo(L + r, h + tabH); s.quadraticCurveTo(L, h + tabH, L, h + tabH - r);
+ s.lineTo(L, r); s.quadraticCurveTo(L, 0, L + r, 0);
+ return s;
+}
+export const ext = (shape, depth, bevel, curveSegments = 18) =>
+ new THREE.ExtrudeGeometry(shape, { depth, bevelEnabled: true, bevelThickness: bevel, bevelSize: bevel, bevelSegments: 3, curveSegments });
+const shadowed = (...ms) => ms.forEach(m => { m.castShadow = true; m.receiveShadow = true; });
+
+/* ---------- folder rig (glossy File Explorer folder made real) ---------- */
+export const FOLDER = { W: 2.7, H: 1.9, FLAP: 1.62, GAP: 0.34, TH: 0.035 };
+// hinge.rotation.x: 0 = closed, ~36° = open toward camera.
+export function makeFolder() {
+ const { W, H, FLAP, GAP, TH } = FOLDER;
+ const group = new THREE.Group();
+ const back = new THREE.Mesh(ext(backShape(W, H, 0.09, 0.95, 0.24), TH, 0.012), MAT.folderBack);
+ back.position.z = -GAP / 2 - TH;
+ const base = new THREE.Mesh(new THREE.BoxGeometry(W - 0.02, TH, GAP + TH), MAT.folderBack);
+ base.position.set(0, TH / 2, 0);
+ const hinge = new THREE.Group(); hinge.position.set(0, 0, GAP / 2); // flap hinges on its bottom edge
+ const flap = new THREE.Mesh(ext(roundedRect(W, FLAP, 0.09), TH, 0.012), MAT.folderFront);
+ hinge.add(flap);
+ group.add(back, base, hinge);
+ shadowed(back, base, flap);
+ return { group, hinge, back, base, flap };
+}
+
+/* ---------- cards (thick white matte cardstock, label printed in dark ink) ---------- */
+export const CARD = { W: 2.3, H: 1.55, T: 0.028 };
+export const LABELS = ["Captions", "B-roll", "SFX", "Music", "Color", "Tracking"];
+
+// Paper face with fibre noise. draw(g, W, H) prints the content in ink on top.
+export function paperTexture(seed, draw, w = CARD.W, h = CARD.H) {
+ const W = 1024, H = Math.round(W * h / w), c = document.createElement("canvas"); c.width = W; c.height = H;
+ const g = c.getContext("2d");
+ g.fillStyle = "#F6F5F1"; g.beginPath(); g.roundRect(0, 0, W, H, 0.07 / w * W); g.fill();
+ const rnd = mulberry32(100 + seed), d = g.getImageData(0, 0, W, H);
+ for (let i = 0; i < d.data.length; i += 4) { if (!d.data[i + 3]) continue; const n = (rnd() - 0.5) * 9; d.data[i] += n; d.data[i + 1] += n; d.data[i + 2] += n; }
+ g.putImageData(d, 0, 0);
+ draw(g, W, H);
+ const t = new THREE.CanvasTexture(c); t.colorSpace = THREE.SRGBColorSpace; t.anisotropy = 8;
+ return t;
+}
+export function labelDraw(label, idx) {
+ return (g, W) => {
+ g.fillStyle = "rgba(28,28,30,0.93)"; g.font = "700 84px ID"; g.textBaseline = "alphabetic";
+ g.shadowColor = "rgba(28,28,30,0.35)"; g.shadowBlur = 1.2;
+ g.fillText(label, 56, 98);
+ g.font = "400 46px ID"; g.fillStyle = "rgba(28,28,30,0.42)"; g.textAlign = "right";
+ g.fillText(String(idx + 1).padStart(2, "0"), W - 58, 92);
+ g.textAlign = "left"; g.shadowBlur = 0;
+ };
+}
+const cardGeo = ext(roundedRect(CARD.W, CARD.H, 0.07), CARD.T, 0.006);
+const faceGeo = new THREE.PlaneGeometry(CARD.W, CARD.H); faceGeo.translate(0, CARD.H / 2, 0);
+// Card origin = bottom-centre of its face; it stands in +y, faces +z. card.face.material.map is the print.
+export function makeCard(seed, draw) {
+ const group = new THREE.Group();
+ const body = new THREE.Mesh(cardGeo, MAT.cardEdge);
+ // alphaTest (not transparent) so the print stays in the glass transmission pass (loupe in a generic material scene)
+ const face = new THREE.Mesh(faceGeo, new THREE.MeshStandardMaterial({ map: paperTexture(seed, draw), roughness: 0.88, alphaTest: 0.5 }));
+ face.position.z = CARD.T + 0.0075;
+ body.castShadow = true; body.receiveShadow = true; face.receiveShadow = true;
+ group.add(body, face);
+ group.userData = { face, seed, draw };
+ return group;
+}
+// Reprint after fonts load (canvas text drawn before the font arrives falls back to a system face).
+export function reprint(card) {
+ const { face, seed, draw } = card.userData, m = face.material;
+ m.map.dispose(); m.map = paperTexture(seed, draw); m.needsUpdate = true;
+}
+
+/* ---------- beat wiring: one paused timeline, seek-safe, fonts gate readiness ---------- */
+// Word times in the markup are on the cut timeline; this returns the host slot's start.
+export function hostStart(id, fallback) {
+ const host = [...document.querySelectorAll(`[data-composition-id="${id}"]`)].find(e => e.hasAttribute("data-start"));
+ const value = host ? Number(host.getAttribute("data-start")) : fallback;
+ if (!Number.isFinite(value)) throw new TypeError("host start must be finite");
+ return value;
+}
+export function wireBeat({ id, T0, DUR, renderAt, words, ready, onFonts,
+ fontLoads = ["700 84px ID", "400 46px ID"],
+ wordMotion = { blur: 14, y: 18, scale: 1.07, duration: 0.34, anticipation: 0.06, ease: "power2.out" } }) {
+ if (!id || !Number.isFinite(T0) || !Number.isFinite(DUR) || DUR <= 0 || typeof renderAt !== "function") {
+ throw new TypeError("wireBeat requires an id, finite start, positive duration and renderAt");
+ }
+ if (!wordMotion || ![wordMotion.blur, wordMotion.y, wordMotion.scale,
+ wordMotion.duration, wordMotion.anticipation].every(Number.isFinite) ||
+ wordMotion.blur < 0 || wordMotion.scale <= 0 || wordMotion.duration < 0 ||
+ wordMotion.anticipation < 0 || typeof wordMotion.ease !== "string") {
+ throw new TypeError("invalid selected word motion");
+ }
+ window.__timelines = window.__timelines || {};
+ window.__hf = window.__hf || {};
+ window.__hf.beatDisposers = window.__hf.beatDisposers || {};
+ if (window.__hf.beatDisposers[id]) window.__hf.beatDisposers[id]();
+ let active = true, assetsReady = false, requestedTime = 0;
+ const tl = gsap.timeline({ paused: true });
+ const S = { t: 0 };
+ // Timeline declares duration; hf-seek alone owns canvas poses. GSAP rounds
+ // tweened values, so rendering again from its proxy can overwrite an exact pose.
+ tl.fromTo(S, { t: 0 }, { t: DUR, duration: DUR, ease: "none" }, 0);
+ // kinetic words: blur in on their spoken time (draft motion option)
+ (words ? document.querySelectorAll(words) : []).forEach(w => {
+ const at = parseFloat(w.dataset.t) - T0;
+ if (!Number.isFinite(at)) throw new TypeError("word requires finite cut-timeline data-t");
+ const m = wordMotion;
+ tl.fromTo(w, { opacity: 0, filter: `blur(${m.blur}px)`, y: m.y, scale: m.scale },
+ { opacity: 1, filter: "blur(0px)", y: 0, scale: 1, duration: m.duration, ease: m.ease }, Math.max(0, at - m.anticipation));
+ });
+ const onSeek = e => {
+ const g = e && e.detail && e.detail.time;
+ if (Number.isFinite(g)) {
+ requestedTime = Math.max(0, Math.min(DUR, g - hostStart(id, T0)));
+ if (active && assetsReady) renderAt(requestedTime);
+ }
+ };
+ window.addEventListener("hf-seek", onSeek);
+ window.__timelines[id] = tl;
+ window.__hf.buildReady = window.__hf.buildReady || {};
+ const buildReady = Promise.all([...fontLoads.map(async font => { const faces = await document.fonts.load(font); if (!faces.length) throw new Error(`required font unavailable: ${font}`); return faces; }), ...(ready || [])])
+ .then(() => { if (!active) return; if (onFonts) onFonts(); renderAt(DUR * 0.5); renderAt(requestedTime); assetsReady = true; });
+ // Log rejection without converting the authoritative readiness promise to success.
+ buildReady.catch(error => console.error(`3D beat ${id} failed readiness`, error));
+ window.__hf.buildReady[id] = buildReady;
+ window.__hf.beatDisposers[id] = () => {
+ active = false;
+ window.removeEventListener("hf-seek", onSeek);
+ tl.kill();
+ if (window.__timelines[id] === tl) delete window.__timelines[id];
+ if (window.__hf.buildReady[id] === buildReady) delete window.__hf.buildReady[id];
+ delete window.__hf.beatDisposers[id];
+ };
+ return tl;
+}
+
+export function loadTexture(url, { color = true } = {}) {
+ return new Promise((res, reject) => new THREE.TextureLoader().load(url, t => { t.colorSpace = color ? THREE.SRGBColorSpace : THREE.NoColorSpace; t.anisotropy = 8; res(t); }, undefined, () => reject(new Error(`required texture failed: ${url}`))));
+}
+export function loadImage(url) {
+ return new Promise((res, reject) => { const i = new Image(); i.onload = () => res(i); i.onerror = () => reject(new Error(`required image failed: ${url}`)); i.src = url; });
+}
diff --git a/Editing_OS/Tools/editing-workbench/GUIDE.md b/Editing_OS/Tools/editing-workbench/GUIDE.md
index 442fd8d..60c076f 100644
--- a/Editing_OS/Tools/editing-workbench/GUIDE.md
+++ b/Editing_OS/Tools/editing-workbench/GUIDE.md
@@ -29,3 +29,7 @@ Resolve Lua/MCP offers bounded reads and an authorized verified-empty-project co
The launcher retains GUI/CLI modes with owned previews. Closing it stops its process tree; occupied port 3100 is refused. Windows child consoles are suppressed, logs stay external and no sign-in service or automatic install is created.
Code is MIT; this guide is CC BY 4.0 with MIT snippets. See [workflow](../../../docs/workflow.md) and [optional tools](../../../docs/optional-tools.md).
+
+## New diagnostic/draft capabilities
+
+audio_motion.py analyzes conformed PCM with rational FPS and source hashes. style_inspect.py requires the optional pinned Pillow profile and supplies bounded ROI/alpha/palette observations. capability_examples.py generates external synthetic PCM/image/studio jobs only with an explicit draft flag; test_studio3d.py is an isolated required browser profile. None grants production approval. New external3D fields three_module and puppeteer_entry are optional; old configs remain valid.
diff --git a/Editing_OS/Tools/editing-workbench/audio_motion.py b/Editing_OS/Tools/editing-workbench/audio_motion.py
new file mode 100644
index 0000000..10c4c45
--- /dev/null
+++ b/Editing_OS/Tools/editing-workbench/audio_motion.py
@@ -0,0 +1,157 @@
+"""Offline, frame-indexed music analysis. No third-party runtime or render authority."""
+from __future__ import annotations
+
+import argparse
+from array import array
+import cmath
+from fractions import Fraction
+import hashlib
+import json
+import math
+from pathlib import Path
+import sys
+sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
+import runtime_paths as runtime
+import wave
+
+
+def fft(values: list[float]) -> list[complex]:
+ """Radix-2 FFT; input length must be a power of two."""
+ n = len(values)
+ if n < 2 or n & (n - 1):
+ raise ValueError("FFT size must be a power of two >= 2")
+ output = [complex(v) for v in values]
+ j = 0
+ for i in range(1, n):
+ bit = n >> 1
+ while j & bit:
+ j ^= bit
+ bit >>= 1
+ j ^= bit
+ if i < j:
+ output[i], output[j] = output[j], output[i]
+ size = 2
+ while size <= n:
+ rotation = cmath.exp(-2j * math.pi / size)
+ for start in range(0, n, size):
+ weight = 1 + 0j
+ for k in range(size // 2):
+ left = output[start + k]
+ right = weight * output[start + k + size // 2]
+ output[start + k] = left + right
+ output[start + k + size // 2] = left - right
+ weight *= rotation
+ size *= 2
+ return output
+
+
+def analyze(path: Path, fps: str = "30", bands: int = 24,
+ fft_size: int = 1024, attack_ms: float = 35,
+ release_ms: float = 180) -> dict:
+ rate = Fraction(fps)
+ if not 1 <= rate <= 120:
+ raise ValueError("FPS must be between 1 and 120; rational rates supported")
+ if not 4 <= bands <= 64:
+ raise ValueError("bands must be between 4 and 64")
+ if fft_size not in (512, 1024, 2048, 4096):
+ raise ValueError("FFT size must be 512, 1024, 2048 or 4096")
+ if not all(math.isfinite(v) and 0 <= v <= 2000 for v in (attack_ms, release_ms)):
+ raise ValueError("smoothing times must be finite, from 0 to 2000 ms")
+ with path.open("rb") as handle:
+ identity = hashlib.file_digest(handle, "sha256").hexdigest()
+ window = [0.5 - 0.5 * math.cos(2 * math.pi * i / (fft_size - 1))
+ for i in range(fft_size)]
+ gain = 2 / sum(window)
+ with wave.open(str(path), "rb") as source:
+ sample_rate, channels, samples = source.getframerate(), source.getnchannels(), source.getnframes()
+ if source.getsampwidth() != 2 or source.getcomptype() != "NONE":
+ raise ValueError("analysis requires uncompressed signed 16-bit PCM WAV")
+ if samples <= 0 or not 8000 <= sample_rate <= 192000 or not 1 <= channels <= 8:
+ raise ValueError("empty or unsupported audio geometry")
+ duration = Fraction(samples, sample_rate)
+ frame_count = math.ceil(duration * rate)
+ if frame_count > 72000:
+ raise ValueError("analysis exceeds 72000 frames; analyze a reviewed excerpt")
+ edges = [40 * (sample_rate / 2 / 40) ** (i / bands) for i in range(bands + 1)]
+ bins = []
+ for lo, hi in zip(edges, edges[1:]):
+ indices = [k for k in range(1, fft_size // 2 + 1)
+ if lo <= k * sample_rate / fft_size < hi]
+ bins.append(indices or [max(1, min(fft_size // 2, round(math.sqrt(lo * hi) * fft_size / sample_rate)))])
+ attack = math.exp(-1 / (float(rate) * attack_ms / 1000)) if attack_ms else 0
+ release = math.exp(-1 / (float(rate) * release_ms / 1000)) if release_ms else 0
+ previous = [0.0] * bands
+ frames = []
+ for frame in range(frame_count):
+ center = int(Fraction(frame, 1) / rate * sample_rate)
+ left = center - fft_size // 2
+ begin, end = max(0, left), min(samples, left + fft_size)
+ source.setpos(begin)
+ raw = source.readframes(end - begin)
+ if len(raw) != (end - begin) * channels * 2:
+ raise ValueError("truncated PCM data")
+ pcm = array("h")
+ pcm.frombytes(raw)
+ if sys.byteorder != "little":
+ pcm.byteswap()
+ energy = [0.0] * (fft_size // 2 + 1)
+ square_sum = 0.0
+ peak = 0.0
+ for channel in range(channels):
+ signal = [0.0] * fft_size
+ for i in range(end - begin):
+ value = pcm[i * channels + channel] / 32768
+ signal[begin - left + i] = value
+ square_sum += value * value
+ peak = max(peak, abs(value))
+ spectrum = fft([v * w for v, w in zip(signal, window)])
+ for k in range(len(energy)):
+ energy[k] += (abs(spectrum[k]) * gain) ** 2 / channels
+ levels = []
+ for band, indices in enumerate(bins):
+ amplitude = math.sqrt(sum(energy[k] for k in indices) / len(indices))
+ dbfs = 20 * math.log10(max(amplitude, 1e-12))
+ target = max(0.0, min(1.0, (dbfs + 80) / 80))
+ coefficient = attack if target > previous[band] else release
+ previous[band] = coefficient * previous[band] + (1 - coefficient) * target
+ levels.append(round(previous[band], 6))
+ # Mean channel energy prevents opposite-phase stereo from becoming false silence.
+ rms = math.sqrt(square_sum / ((end - begin) * channels))
+ frames.append({"rms": round(rms, 6), "peak": round(peak, 6), "bands": levels})
+ return {"format": "editing-pack-audio-motion/v1", "source_sha256": identity,
+ "sample_rate_hz": sample_rate, "channels": channels,
+ "duration_seconds": float(duration), "fps": str(rate), "frame_count": frame_count,
+ "fft_size": fft_size, "band_edges_hz": [round(v, 3) for v in edges],
+ "scale": {"floor_dbfs": -80, "ceiling_dbfs": 0,
+ "attack_ms": attack_ms, "release_ms": release_ms}, "frames": frames}
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(description=__doc__)
+ runtime.common_args(parser)
+ parser.add_argument("audio", type=Path)
+ parser.add_argument("--out", required=True, type=Path)
+ parser.add_argument("--fps", default="30")
+ parser.add_argument("--bands", type=int, default=24)
+ parser.add_argument("--fft-size", type=int, default=1024)
+ parser.add_argument("--attack-ms", type=float, default=35)
+ parser.add_argument("--release-ms", type=float, default=180)
+ args = parser.parse_args()
+ try:
+ runtime.configure_args(args)
+ args.out = runtime.output(args.out, require_workspace=True)
+ if args.audio.resolve() == args.out.resolve() or args.out.exists():
+ raise ValueError("output must be new and must not replace the source")
+ data = analyze(args.audio, args.fps, args.bands, args.fft_size, args.attack_ms, args.release_ms)
+ with args.out.open("x", encoding="utf-8") as handle:
+ json.dump(data, handle, ensure_ascii=False, allow_nan=False, separators=(",", ":"))
+ handle.write("\n")
+ print(f"Analyzed {data['frame_count']} frames at {data['fps']} FPS. Not render/QA approval.")
+ return 0
+ except (OSError, ValueError, ZeroDivisionError, wave.Error) as exc:
+ print(f"Audio analysis failed: {exc}", file=sys.stderr)
+ return 2
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/Editing_OS/Tools/editing-workbench/capability_examples.py b/Editing_OS/Tools/editing-workbench/capability_examples.py
new file mode 100644
index 0000000..da6a2ee
--- /dev/null
+++ b/Editing_OS/Tools/editing-workbench/capability_examples.py
@@ -0,0 +1,166 @@
+"""MIT. Generated-input demonstrations; never production or human-approval evidence."""
+from __future__ import annotations
+import argparse
+from array import array
+import hashlib
+import importlib.util
+import json
+import math
+from pathlib import Path
+import re
+import shutil
+import subprocess
+import sys
+import wave
+sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
+import runtime_paths as runtime
+
+
+def load(name, path):
+ spec = importlib.util.spec_from_file_location(name, path)
+ module = importlib.util.module_from_spec(spec)
+ sys.modules[name] = module
+ spec.loader.exec_module(module)
+ return module
+
+
+def write(path, data):
+ path.parent.mkdir(parents=True, exist_ok=True)
+ with path.open('x', encoding='utf-8') as stream:
+ json.dump(data, stream, indent=2, allow_nan=False)
+ stream.write('\n')
+
+
+def stage_studio(job, example):
+ resources = runtime.studio_resources()
+ root = runtime.root() / 'Editing_OS/Skills/studio-3d-objects/starter'
+ copies = {'assets/three/three.module.js': resources['three_module'],
+ 'assets/three/three.core.js': resources['three_core'],
+ 'assets/three/addons/environments/RoomEnvironment.js': resources['room_environment'],
+ 'assets/js/gsap.min.js': resources['gsap_runtime'], 'assets/js/studio3d.js': root / 'studio3d.js',
+ 'assets/css/stage.css': root / 'stage.css',
+ 'assets/fonts/inter-regular.woff2': resources['inter_regular_font'],
+ 'assets/fonts/inter-bold.woff2': resources['inter_bold_font'],
+ 'compositions/scene.html': root / 'examples' / (example + '.html')}
+ inventory = []
+ for name, source in copies.items():
+ dest = runtime.output(job / name, require_workspace=True)
+ dest.parent.mkdir(parents=True, exist_ok=True)
+ shutil.copyfile(source, dest)
+ inventory.append({'file': name, 'sha256': hashlib.sha256(dest.read_bytes()).hexdigest()})
+ for label, package in [('three', resources['three_module'].parent.parent),
+ ('gsap', resources['gsap_runtime'].parent.parent), ('inter', resources['inter_regular_font'].parent.parent)]:
+ licenses = sorted(package.glob('LICENSE*'))
+ if not licenses and label == 'gsap':
+ notice = job / 'notices/GSAP.txt'
+ notice.parent.mkdir(parents=True, exist_ok=True)
+ notice.write_text('GSAP retains its embedded GreenSock copyright and custom Standard License. Terms: https://gsap.com/standard-license/. Not toolkit MIT.\n', encoding='utf-8')
+ inventory.append({'file': 'notices/GSAP.txt', 'sha256': hashlib.sha256(notice.read_bytes()).hexdigest()})
+ elif not licenses:
+ raise ValueError('Missing required installed resource license: ' + label)
+ for source in licenses:
+ dest = job / 'notices' / (label + '-' + source.name)
+ dest.parent.mkdir(parents=True, exist_ok=True)
+ shutil.copyfile(source, dest)
+ inventory.append({'file': dest.relative_to(job).as_posix(), 'sha256': hashlib.sha256(dest.read_bytes()).hexdigest()})
+ scene_id = 'draft-' + example
+ html = 'Synthetic 3D draft '
+ html += ''
+ html += ''
+ html += ''
+ (job / 'index.html').write_text(html, encoding='utf-8', newline='\n')
+ write(job / 'runtime-assets.json', {'synthetic': True, 'production_authority': False, 'resources': inventory})
+
+
+def run_command(args, cwd, log, timeout=600):
+ process = subprocess.Popen(args, cwd=cwd, env=runtime.child_env(), stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, text=True, encoding='utf-8', errors='replace', **runtime.child_kwargs())
+ try:
+ stdout, stderr = process.communicate(timeout=timeout)
+ except subprocess.TimeoutExpired:
+ if process.poll() is None:
+ if sys.platform == 'win32':
+ subprocess.run(['taskkill', '/PID', str(process.pid), '/T', '/F'], capture_output=True, **runtime.child_kwargs())
+ else:
+ process.kill()
+ stdout, stderr = process.communicate()
+ log.write_text(stdout + stderr, encoding='utf-8')
+ raise ValueError('Owned demo process timed out; diagnostics retained')
+ log.write_text(stdout + stderr, encoding='utf-8')
+ if process.returncode:
+ raise ValueError('Demo command failed; inspect ' + log.name)
+
+
+def main(argv=None):
+ p = argparse.ArgumentParser(description=__doc__)
+ runtime.common_args(p)
+ p.add_argument('kind', choices=['audio', 'style', 'studio'])
+ p.add_argument('--job-name', required=True)
+ p.add_argument('--allow-unapproved-draft-treatment', action='store_true')
+ p.add_argument('--example', choices=['folder-cards-rise', 'cards-scatter-file-in', 'mat-loupe-stamp', 'monitor-timeline', 'tablet-over-footage'], default='folder-cards-rise')
+ p.add_argument('--render', action='store_true')
+ p.add_argument('--capture', choices=['software', 'hardware'], default='software')
+ args = p.parse_args(argv)
+ try:
+ runtime.configure_args(args)
+ if args.render and args.kind != 'studio':
+ raise ValueError('--render is supported only for studio; audio/style produce analysis fixtures')
+ if not args.allow_unapproved_draft_treatment:
+ raise ValueError('Synthetic demonstrations require explicit --allow-unapproved-draft-treatment; this never grants publication authority')
+ if not re.fullmatch(r'[A-Za-z0-9_-]+', args.job_name) or re.fullmatch(r'(?i)(con|prn|aux|nul|com[1-9]|lpt[1-9])', args.job_name):
+ raise ValueError('Use a safe ASCII job name')
+ job = runtime.output(runtime.workspace_root() / 'jobs' / args.job_name, require_workspace=True)
+ if job.exists():
+ raise ValueError('Job exists; use a new name, no overwrite')
+ if args.kind == 'style':
+ inspector = load('example_style', Path(__file__).with_name('style_inspect.py'))
+ if inspector.Image is None:
+ raise ValueError('Install optional requirements-style.lock.txt first')
+ if args.kind == 'studio':
+ runtime.studio_resources()
+ job.mkdir(parents=True)
+ (job / 'evidence').mkdir()
+ (job / 'cache').mkdir()
+ write(job / 'fixture-status.json', {'synthetic': True, 'production_authority': False,
+ 'selected_by_human': False, 'publication_approved': False, 'kind': args.kind})
+ if args.kind == 'audio':
+ path = job / 'generated-pcm.wav'
+ rate = 16000
+ samples = array('h', (int(9000 * math.sin(2 * math.pi * (440 if i < rate else 880) * i / rate)) for i in range(rate * 2)))
+ if sys.byteorder != 'little':
+ samples.byteswap()
+ with wave.open(str(path), 'wb') as wav:
+ wav.setnchannels(1); wav.setsampwidth(2); wav.setframerate(rate); wav.writeframes(samples.tobytes())
+ motion = load('example_audio', Path(__file__).with_name('audio_motion.py'))
+ data = motion.analyze(path, fps='30000/1001')
+ write(job / 'evidence/audio-motion.json', data)
+ elif args.kind == 'style':
+ image = inspector.Image.new('RGBA', (160, 100), '#101820')
+ image.paste('#3DD6D0', (20, 20, 70, 80)); image.paste('#F7BA1E', (80, 20, 140, 80))
+ path = job / 'generated-palette.png'; image.save(path)
+ data = inspector.inspect_image(path, roi=[20, 20, 120, 60], subject=[20, 20, 50, 60])
+ write(job / 'evidence/style-observations.json', {'synthetic': True, 'production_authority': False, 'images': [data]})
+ else:
+ stage_studio(job, args.example)
+ if args.render:
+ run_command(runtime.hyperframes_command(['check', '--json', '--at', '0.2,1.3,2.7']), job, job / 'cache/check.log')
+ (job / 'exports').mkdir()
+ output = job / 'exports/synthetic-3d-DRAFT.mp4'
+ mode = '--no-browser-gpu' if args.capture == 'software' else '--browser-gpu'
+ run_command(runtime.hyperframes_command(['render', '--quality', 'draft', mode, '--workers', '1', '--output', str(output)]), job, job / 'cache/render.log')
+ quality = load('example_quality', runtime.root() / 'Editing_OS/Video Editing/Engines/Quality_engine/qa.py')
+ report = quality.run_quality_audit(output, scan_scenes=False)
+ write(job / 'evidence/quality-report.json', report)
+ if not report['decode_integrity']['passed'] or report['ready']:
+ raise ValueError('Draft decode failed or missing publication authority unexpectedly passed')
+ print(json.dumps({'job': str(job), 'synthetic': True, 'ready': False, 'publication_approved': False}))
+ return 0
+ except (OSError, ValueError) as exc:
+ print('Draft demonstration failed: ' + str(exc), file=sys.stderr)
+ return 2
+
+
+if __name__ == '__main__':
+ raise SystemExit(main())
diff --git a/Editing_OS/Tools/editing-workbench/style_inspect.py b/Editing_OS/Tools/editing-workbench/style_inspect.py
new file mode 100644
index 0000000..e6ea56b
--- /dev/null
+++ b/Editing_OS/Tools/editing-workbench/style_inspect.py
@@ -0,0 +1,163 @@
+"""Local still-image observations, not style recognition or production approval."""
+from __future__ import annotations
+
+import argparse
+from collections import Counter
+import hashlib
+import io
+import json
+import math
+from pathlib import Path
+import re
+import sys
+sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
+import runtime_paths as runtime
+
+try:
+ from PIL import Image, ImageOps
+except ImportError:
+ Image = ImageOps = None
+_DECOMPRESSION_BOMB = Image.DecompressionBombError if Image is not None else ValueError
+
+MAX_BYTES = 64 * 1024 * 1024
+MAX_PIXELS = 40_000_000
+MAX_DIMENSION = 20_000
+MAX_SAMPLES = 200_000
+FORMATS = {"PNG", "JPEG", "WEBP", "TIFF", "BMP"}
+
+
+def rect(value, width, height, label):
+ if value is None:
+ return (0, 0, width, height)
+ if len(value) != 4 or any(type(v) is not int for v in value):
+ raise ValueError(f"{label} must be four integer display-pixel coordinates")
+ x, y, w, h = value
+ if x < 0 or y < 0 or w <= 0 or h <= 0 or x + w > width or y + h > height:
+ raise ValueError(f"{label} is empty or outside the display image")
+ return tuple(value)
+
+
+def linear_srgb(channel):
+ value = channel / 255
+ return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4
+
+
+def inspect_image(path: Path, roi=None, subject=None, matte=None):
+ if Image is None:
+ raise ValueError("Missing optional Pillow; install requirements-style.lock.txt in the selected environment")
+ path = Path(path)
+ if not path.is_file():
+ raise ValueError(f"Local image does not exist: {path}")
+ if path.stat().st_size > MAX_BYTES:
+ raise ValueError("Image file exceeds the 64 MiB limit")
+ if matte is not None and not re.fullmatch(r"#[0-9a-fA-F]{6}", matte):
+ raise ValueError("Matte must be #RRGGBB")
+ content = path.read_bytes()
+ if len(content) > MAX_BYTES:
+ raise ValueError("Image file exceeds the 64 MiB limit")
+ digest = hashlib.sha256(content)
+ # Decode the same bounded byte snapshot that was hashed, even if the source changes.
+ with Image.open(io.BytesIO(content)) as source:
+ if source.format not in FORMATS:
+ raise ValueError("Use a PNG, JPEG, WebP, TIFF or BMP still")
+ if getattr(source, "n_frames", 1) != 1:
+ raise ValueError("Animated or multi-page inputs must be extracted to one still")
+ raw_size = source.size
+ if max(raw_size) > MAX_DIMENSION or raw_size[0] * raw_size[1] > MAX_PIXELS:
+ raise ValueError("Image dimensions exceed the diagnostic limits")
+ orientation = source.getexif().get(274, 1)
+ if type(orientation) is not int or orientation not in range(1, 9):
+ raise ValueError("Unsupported EXIF orientation; use a verified display still")
+ image = ImageOps.exif_transpose(source).convert("RGBA")
+ width, height = image.size
+ x, y, w, h = rect(roi, width, height, "ROI")
+ subject_box = rect(subject, width, height, "Subject") if subject is not None else None
+ if subject_box:
+ sx, sy, sw, sh = subject_box
+ if sx < x or sy < y or sx + sw > x + w or sy + sh > y + h:
+ raise ValueError("Declared subject must be inside the ROI")
+ # No resampling: palette observations should not manufacture blended colors.
+ stride = max(1, math.ceil(math.sqrt(w * h / MAX_SAMPLES)))
+ while math.ceil(w / stride) * math.ceil(h / stride) > MAX_SAMPLES:
+ stride += 1
+ pixels = image.load()
+ colors = Counter()
+ sums = {}
+ sampled = included = partial = invisible = 0
+ luminance_sum = 0.0
+ dark = light = 0
+ matte_rgb = tuple(int(matte[i:i + 2], 16) for i in (1, 3, 5)) if matte else None
+ for py in range(y, y + h, stride):
+ for px in range(x, x + w, stride):
+ r, g, b, a = pixels[px, py]
+ sampled += 1
+ invisible += int(a == 0)
+ partial += int(0 < a < 255)
+ if matte_rgb is None and a != 255:
+ continue
+ if matte_rgb is not None:
+ r, g, b = [round(c * a / 255 + m * (1 - a / 255)) for c, m in zip((r, g, b), matte_rgb)]
+ included += 1
+ key = (r // 16, g // 16, b // 16)
+ colors[key] += 1
+ accumulator = sums.setdefault(key, [0, 0, 0])
+ for index, channel in enumerate((r, g, b)):
+ accumulator[index] += channel
+ lum = 0.2126 * linear_srgb(r) + 0.7152 * linear_srgb(g) + 0.0722 * linear_srgb(b)
+ luminance_sum += lum
+ dark += int(lum < 0.05)
+ light += int(lum > 0.8)
+ palette = []
+ for key, count in sorted(colors.items(), key=lambda pair: (-pair[1], pair[0]))[:12]:
+ rgb = [round(v / count) for v in sums[key]]
+ palette.append({"mean_rgb": rgb, "hex": "#" + "".join(f"{v:02X}" for v in rgb), "sample_count": count, "fraction_of_included_samples": round(count / included, 6)})
+ report = {
+ "path": str(path.resolve()), "source_sha256": digest.hexdigest(),
+ "raw_dimensions": list(raw_size), "display_dimensions": [width, height],
+ "exif_orientation": orientation, "exif_orientation_normalized": orientation not in (None, 1),
+ "roi_display_xywh": [x, y, w, h], "sample_stride_pixels": stride,
+ "sample_count": sampled, "included_samples": included,
+ "transparent_samples": invisible, "partial_alpha_samples": partial,
+ "alpha_policy": "opaque_only" if matte is None else "encoded_RGB_composite",
+ "matte_rgb": list(matte_rgb) if matte_rgb else None,
+ "color_interpretation": "Stored RGB values interpreted as sRGB; embedded ICC profiles are not converted.",
+ "palette_quantization_step": 16, "palette": palette,
+ "relative_luminance": {"mean": round(luminance_sum / included, 6) if included else None, "fraction_below_0_05": round(dark / included, 6) if included else None, "fraction_above_0_8": round(light / included, 6) if included else None},
+ "declared_subject": None,
+ "limitations": ["Sampled color buckets do not assign semantic palette roles.", "Declared bounds are not segmentation or visible silhouette area.", "No font, material, light, motion, artistic similarity or readiness inference.", "Sampling can miss thin lines, small accents and texture."],
+ }
+ if subject_box:
+ sx, sy, sw, sh = subject_box
+ report["declared_subject"] = {"display_xywh": list(subject_box), "normalized_xywh_in_roi": [round((sx - x) / w, 6), round((sy - y) / h, 6), round(sw / w, 6), round(sh / h, 6)], "bounding_box_area_fraction": round(sw * sh / (w * h), 6)}
+ return report
+
+
+def main(argv=None):
+ parser = argparse.ArgumentParser(description=__doc__)
+ runtime.common_args(parser)
+ parser.add_argument("images", type=Path, nargs="+")
+ parser.add_argument("--roi", type=int, nargs=4, metavar=("X", "Y", "WIDTH", "HEIGHT"))
+ parser.add_argument("--subject", type=int, nargs=4, metavar=("X", "Y", "WIDTH", "HEIGHT"))
+ parser.add_argument("--matte", help="Explicit #RRGGBB ground for alpha compositing")
+ parser.add_argument("--out", type=Path, required=True)
+ args = parser.parse_args(argv)
+ try:
+ runtime.configure_args(args)
+ args.out = runtime.output(args.out, require_workspace=True)
+ if args.out.exists():
+ raise ValueError("Output exists; choose a new path")
+ observations = [inspect_image(p, args.roi, args.subject, args.matte) for p in args.images]
+ payload = {"record_type": "local-style-reference-observations", "images": observations, "production_authority": False}
+ encoded = json.dumps(payload, indent=2, allow_nan=False)
+ # Exclusive creation also protects against a path appearing during analysis.
+ with args.out.open("x", encoding="utf-8") as stream:
+ stream.write(encoded + "\n")
+ except (OSError, ValueError, _DECOMPRESSION_BOMB) as error:
+ print(f"ERROR: {error}", file=sys.stderr)
+ return 1
+ print(f"Observed {len(observations)} still(s): {args.out}")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/Editing_OS/Tools/editing-workbench/test_audio_motion.py b/Editing_OS/Tools/editing-workbench/test_audio_motion.py
new file mode 100644
index 0000000..b4f5f4e
--- /dev/null
+++ b/Editing_OS/Tools/editing-workbench/test_audio_motion.py
@@ -0,0 +1,112 @@
+"""Signal and boundary regression coverage for the owned audio-motion helper."""
+import importlib.util
+import math
+from pathlib import Path
+import struct
+import subprocess
+import sys
+import tempfile
+import unittest
+import wave
+
+spec = importlib.util.spec_from_file_location("audio_motion", Path(__file__).with_name("audio_motion.py"))
+motion = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(motion)
+
+
+class AudioMotionTests(unittest.TestCase):
+ def setUp(self):
+ self.temp = tempfile.TemporaryDirectory()
+ self.root = Path(self.temp.name)
+ self.addCleanup(self.temp.cleanup)
+
+ def wav(self, name="signal.wav", frequency=1000, channels=1, seconds=0.4, silent=False):
+ path = self.root / name
+ with wave.open(str(path), "wb") as handle:
+ handle.setparams((channels, 2, 16000, 0, "NONE", "not compressed"))
+ values = []
+ for i in range(int(16000 * seconds)):
+ value = 0 if silent else round(16384 * math.sin(2 * math.pi * frequency * i / 16000))
+ values.extend([value] if channels == 1 else [value, -value])
+ handle.writeframes(struct.pack("<" + "h" * len(values), *values))
+ return path
+
+ def test_fft_impulse_and_tone(self):
+ impulse = motion.fft([1.0] + [0.0] * 7)
+ self.assertTrue(all(abs(v - 1) < 1e-10 for v in impulse))
+ tone = motion.fft([math.sin(2 * math.pi * i / 8) for i in range(8)])
+ self.assertAlmostEqual(abs(tone[1]), 4)
+ self.assertAlmostEqual(abs(tone[7]), 4)
+
+ def test_silence_is_zero(self):
+ data = motion.analyze(self.wav(silent=True))
+ self.assertEqual(data["frame_count"], 12)
+ self.assertTrue(all(f["rms"] == f["peak"] == 0 and not any(f["bands"]) for f in data["frames"]))
+
+ def test_spectrum_tracks_actual_frequency(self):
+ for frequency in (250, 2000):
+ data = motion.analyze(self.wav(f"{frequency}.wav", frequency=frequency), attack_ms=0, release_ms=0)
+ row = data["frames"][5]
+ band = max(range(24), key=lambda i: row["bands"][i])
+ self.assertLessEqual(data["band_edges_hz"][band], frequency)
+ self.assertGreater(data["band_edges_hz"][band + 1], frequency)
+ self.assertAlmostEqual(row["rms"], 0.5 / math.sqrt(2), places=3)
+
+ def test_stereo_phase_does_not_cancel_visualizer(self):
+ mono = motion.analyze(self.wav())
+ stereo = motion.analyze(self.wav("stereo.wav", channels=2))
+ self.assertEqual(mono["frames"], stereo["frames"])
+
+ def test_rational_fps_and_last_frame(self):
+ data = motion.analyze(self.wav(seconds=0.41), fps="30000/1001")
+ self.assertEqual(data["fps"], "30000/1001")
+ self.assertEqual(data["frame_count"], 13)
+ self.assertLess((data["frame_count"] - 1) / (30000 / 1001), data["duration_seconds"])
+
+ def test_repeated_analysis_and_out_of_order_access(self):
+ path = self.wav()
+ first = motion.analyze(path)
+ second = motion.analyze(path)
+ self.assertEqual(first, second)
+ self.assertEqual([first["frames"][i] for i in (10, 0, 5, 10)],
+ [second["frames"][i] for i in (10, 0, 5, 10)])
+ self.assertTrue(all(0 <= v <= 1 for f in first["frames"] for v in f["bands"]))
+
+ def test_invalid_inputs(self):
+ path = self.wav()
+ for kwargs in ({"fps": "0"}, {"fps": "nan"}, {"bands": 0},
+ {"fft_size": 1000}, {"attack_ms": float("nan")}, {"release_ms": -1}):
+ with self.assertRaises((ValueError, ZeroDivisionError)):
+ motion.analyze(path, **kwargs)
+ wrong = self.root / "eight-bit.wav"
+ with wave.open(str(wrong), "wb") as handle:
+ handle.setparams((1, 1, 16000, 0, "NONE", "not compressed"))
+ handle.writeframes(b"\x80" * 512)
+ with self.assertRaisesRegex(ValueError, "16-bit PCM"):
+ motion.analyze(wrong)
+
+ def test_empty_and_truncated_audio_fail(self):
+ empty = self.wav("empty.wav", seconds=0)
+ with self.assertRaisesRegex(ValueError, "empty"):
+ motion.analyze(empty)
+ truncated = self.wav("truncated.wav")
+ truncated.write_bytes(truncated.read_bytes()[:-50])
+ with self.assertRaisesRegex(ValueError, "truncated"):
+ motion.analyze(truncated)
+
+ def test_cli_never_overwrites(self):
+ path = self.wav()
+ original = path.read_bytes()
+ result = subprocess.run([sys.executable, "-B", str(Path(motion.__file__)), str(path), "--out", str(path)], capture_output=True)
+ self.assertEqual(result.returncode, 2)
+ self.assertEqual(path.read_bytes(), original)
+ out = self.root / "motion.json"
+ args = [sys.executable, "-B", str(Path(motion.__file__)), str(path), "--out", str(out)]
+ self.assertEqual(subprocess.run(args, capture_output=True).returncode, 0)
+ saved = out.read_bytes()
+ self.assertEqual(subprocess.run(args, capture_output=True).returncode, 2)
+ self.assertEqual(out.read_bytes(), saved)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Editing_OS/Tools/editing-workbench/test_studio3d.py b/Editing_OS/Tools/editing-workbench/test_studio3d.py
new file mode 100644
index 0000000..383c8e5
--- /dev/null
+++ b/Editing_OS/Tools/editing-workbench/test_studio3d.py
@@ -0,0 +1,45 @@
+"""MIT. Required isolated 3D browser profile: prerequisites fail, never skip."""
+import functools,http.server,json,os
+from pathlib import Path
+import shutil,subprocess,sys,tempfile,threading,unittest
+sys.path.insert(0,str(Path(__file__).resolve().parents[2]))
+import runtime_paths as runtime
+RUNNER = "\nconst {pathToFileURL} = require('node:url');\nconst assert = require('node:assert/strict');\nconst puppeteer = require(process.env.STUDIO3D_PUPPETEER);\n(async () => {\n const browser = await puppeteer.launch({executablePath:process.env.PRODUCER_HEADLESS_SHELL_PATH,\n headless:true, windowsHide:true, userDataDir:process.env.STUDIO3D_PROFILE, args:process.env.EDITING_PACK_3D_CAPTURE==='hardware' ? ['--use-angle=d3d11','--enable-webgl'] : ['--use-gl=angle','--use-angle=swiftshader','--enable-unsafe-swiftshader','--enable-webgl']});\n try {\n const page = await browser.newPage(); const errors=[]; const remote=[];\n page.on('pageerror', e=>errors.push(String(e)));\n await page.setRequestInterception(true);\n page.on('request',r=>{ const u=new URL(r.url());\n if (u.protocol==='http:' && u.hostname==='127.0.0.1') r.continue();\n else if (['data:','about:'].includes(u.protocol)) r.continue();\n else {remote.push(r.url()); r.abort();} });\n await page.goto(process.argv[2], {waitUntil:'networkidle0'});\n await page.waitForFunction(()=>window.suite || window.loadError);\n const result = await page.evaluate(async(processCapture)=>{\n if(window.loadError) throw Error(window.loadError);\n const {m,THREE}=window.suite; const checks=[];\n function check(name, ok){if(!ok)throw Error(name);checks.push(name);}\n check('zero-duration step',m.seg(1,1,0)===1 && m.seg(0,1,0)===0);\n for(const args of [[0,0,-1],[NaN,0,1]]){\n let failed=false;try{m.seg(...args)}catch{failed=true}check('invalid segment rejected '+args,failed);\n }\n let failed=false;try{m.createStage(document.createElement('canvas'),{width:0})}catch{failed=true}\n check('invalid stage rejected',failed);\n const canvas=document.querySelector('canvas');\n const stage=m.createStage(canvas,{width:480,height:270,environmentIntensity:0.8,keyIntensity:1.5});\n const {scene,camera,render,renderer}=stage;\n check('landscape camera and fixed pixels',camera.aspect===480/270 && canvas.width===480 && canvas.height===270);\n check('selected light parameters',scene.environmentIntensity===0.8 && stage.key.intensity===1.5);\n const folder=m.makeFolder();scene.add(folder.group);camera.position.set(0,3.4,12);camera.lookAt(0,1,0);\n const poses=[];\n const renderAt=t=>{folder.hinge.rotation.x=0.65*m.outCubic(m.seg(t,0,1));\n folder.group.position.x=-0.6+1.2*m.seg(t,0,2); render();poses.push(t)};\n m.wireBeat({id:'probe',T0:5,DUR:2,renderAt,fontLoads:[]});await window.__hf.buildReady.probe;\n function seek(t){window.dispatchEvent(new CustomEvent('hf-seek',{detail:{time:t}}))}\n seek(5.4);const a=canvas.toDataURL();seek(6.6);const b=canvas.toDataURL();seek(5.4);\n check('rendered A-B-A pixel determinism',a===canvas.toDataURL() && a!==b);\n for(const t of [6.2,5,7,5.4])seek(t);check('shuffled seek pixel determinism',a===canvas.toDataURL());\n const gl=renderer.getContext();const pixels=new Uint8Array(480*270*4);gl.readPixels(0,0,480,270,gl.RGBA,gl.UNSIGNED_BYTE,pixels);\n let visible=0;for(let i=3;i0)visible++;\n check('nonblank canvas',visible>500);\n const before=poses.length;seek(NaN);check('nonfinite seek ignored',poses.length===before);\n seek(0);check('seek clamps start',poses.at(-1)===0);seek(99);check('seek clamps end',poses.at(-1)===2);\n document.querySelector('#host').dataset.start='10';seek(10.5);check('live host offset',poses.at(-1)===0.5);\n let replacement=0;\n m.wireBeat({id:'probe',T0:10,DUR:2,renderAt:()=>replacement++,fontLoads:[]});await window.__hf.buildReady.probe;\n const oldCount=poses.length;const newCount=replacement;seek(10.4);\n check('same-id old listener removed',poses.length===oldCount && replacement===newCount+1);\n window.__hf.beatDisposers.probe();const disposedCount=replacement;seek(11);\n check('beat cleanup removes registry and listener',!window.__timelines.probe && replacement===disposedCount);\n let release;const held=new Promise(r=>release=r);let heldRenders=0;\n m.wireBeat({id:'held',T0:0,DUR:1,renderAt:()=>heldRenders++,fontLoads:[],ready:[held]});\n window.__hf.beatDisposers.held();release();await held;await new Promise(r=>setTimeout(r,0));\n check('disposed pending beat never warm-renders',heldRenders===0);\n const expected=[];const originalError=console.error;console.error=(...a)=>expected.push(a.join(' '));\n m.wireBeat({id:'bad',T0:0,DUR:1,renderAt:()=>{},fontLoads:[],ready:[Promise.reject(Error('missing required model'))]});\n failed=false;try{await window.__hf.buildReady.bad}catch{failed=true}\n check('failed dependency rejects readiness',failed && expected.length===1);console.error=originalError;\n window.__hf.beatDisposers.bad();\n const originalLoad=document.fonts.load.bind(document.fonts);\n document.fonts.load=async()=>[];console.error=(...a)=>expected.push(a.join(' '));\n m.wireBeat({id:'font-failure',T0:0,DUR:1,renderAt:()=>{},fontLoads:['700 84px MissingRequiredFont']});\n failed=false;try{await window.__hf.buildReady['font-failure']}catch{failed=true}\n check('missing required font rejects readiness',failed);\n document.fonts.load=originalLoad;console.error=originalError;window.__hf.beatDisposers['font-failure']();\n for(const load of [m.loadImage,m.loadTexture]){\n failed=false;try{await load('/missing-required.png')}catch{failed=true}check('required loader rejects '+load.name,failed);\n }\n const png='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jGJkAAAAASUVORK5CYII=';\n const color=await m.loadTexture(png);const data=await m.loadTexture(png,{color:false});\n check('color versus data texture space',color.colorSpace===THREE.SRGBColorSpace && data.colorSpace===THREE.NoColorSpace);\n color.dispose();data.dispose();\n let materialDisposed=0; m.MAT.folderFront.addEventListener('dispose',()=>materialDisposed++);\n stage.dispose();stage.dispose();check('stage cleanup preserves shared materials',materialDisposed===0 && scene.environment===null);\n const portrait=m.createStage(document.createElement('canvas'),{floor:false});\n check('legacy portrait defaults preserved',portrait.camera.aspect===1080/1920 && portrait.renderer.domElement.width===1080);\n portrait.dispose();\n const dbg=gl.getExtension('WEBGL_debug_renderer_info');const gpu=dbg?gl.getParameter(dbg.UNMASKED_RENDERER_WEBGL):gl.getParameter(gl.RENDERER);if(processCapture==='software')check('software renderer verified',/SwiftShader/i.test(gpu));return {checks,visible_pixels:visible,revision:THREE.REVISION,gpu};\n },process.env.EDITING_PACK_3D_CAPTURE || 'software');\n assert.deepEqual(errors,[]);assert.deepEqual(remote,[]);\n console.log(JSON.stringify({...result,page_errors:errors,remote_requests:remote}));\n } finally {await browser.close();}\n})().catch(e=>{console.error(e);process.exitCode=1});\n"
+class QuietHandler(http.server.SimpleHTTPRequestHandler):
+ def log_message(self,*args):pass
+class StudioBrowserTests(unittest.TestCase):
+ def test_offline_scene_lifecycle_readiness_and_random_seek(self):
+ resources=runtime.studio_resources()
+ scratch=runtime.output(runtime.workspace_root()/'cache/studio-tests',require_workspace=True)
+ scratch.mkdir(parents=True,exist_ok=True)
+ with tempfile.TemporaryDirectory(prefix='site-',dir=scratch) as tmp:
+ site=Path(tmp)
+ staged={'three.module.js':resources['three_module'],'three.core.js':resources['three_core'],'addons/environments/RoomEnvironment.js':resources['room_environment'],'gsap.min.js':resources['gsap_runtime']}
+ for name,source in staged.items():
+ dest=site/name;dest.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(source,dest)
+ shutil.copyfile(runtime.root()/'Editing_OS/Skills/studio-3d-objects/starter/studio3d.js',site/'studio3d.js')
+ html='
'
+ html+=''
+ html+=''
+ (site/'index.html').write_text(html,encoding='utf-8');(site/'runner.cjs').write_text(RUNNER,encoding='utf-8')
+ server=http.server.ThreadingHTTPServer(('127.0.0.1',0),functools.partial(QuietHandler,directory=str(site)))
+ thread=threading.Thread(target=server.serve_forever,daemon=True);thread.start()
+ env=runtime.child_env();env['STUDIO3D_PROFILE']=str(site/'browser-profile');env['STUDIO3D_PUPPETEER']=str(resources['puppeteer_entry']);env['PRODUCER_HEADLESS_SHELL_PATH']=str(resources['browser']);env.setdefault('EDITING_PACK_3D_CAPTURE','software')
+ self.assertIn(env['EDITING_PACK_3D_CAPTURE'],('software','hardware'))
+ try:
+ process=subprocess.Popen([str(resources['node']),str(site/'runner.cjs'),f'http://127.0.0.1:{server.server_port}/index.html'],env=env,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True,encoding='utf-8',errors='replace',**runtime.child_kwargs())
+ try:
+ stdout,stderr=process.communicate(timeout=180)
+ except subprocess.TimeoutExpired:
+ if process.poll() is None:
+ if os.name=='nt':subprocess.run(['taskkill','/PID',str(process.pid),'/T','/F'],capture_output=True,**runtime.child_kwargs())
+ else:process.kill()
+ stdout,stderr=process.communicate();(scratch/'timeout.log').write_text(stdout+'\n'+stderr,encoding='utf-8');raise
+ result=subprocess.CompletedProcess(process.args,process.returncode,stdout,stderr)
+ (scratch/'browser-regression.log').write_text(result.stdout+'\n'+result.stderr,encoding='utf-8')
+ self.assertEqual(result.returncode,0,result.stdout+'\n'+result.stderr)
+ report=json.loads(result.stdout.strip().splitlines()[-1]);self.assertGreaterEqual(len(report['checks']),24);self.assertEqual(report['revision'],'185');self.assertEqual(report['remote_requests'],[])
+ (scratch/'browser-regression.json').write_text(json.dumps(report,indent=2),encoding='utf-8');print(json.dumps(report))
+ finally:
+ server.shutdown();server.server_close();thread.join(timeout=5)
+if __name__=='__main__':unittest.main()
diff --git a/Editing_OS/Tools/editing-workbench/test_style_inspect.py b/Editing_OS/Tools/editing-workbench/test_style_inspect.py
new file mode 100644
index 0000000..b7c9de6
--- /dev/null
+++ b/Editing_OS/Tools/editing-workbench/test_style_inspect.py
@@ -0,0 +1,107 @@
+from contextlib import redirect_stderr
+import hashlib
+import io
+from pathlib import Path
+import tempfile
+import unittest
+
+from PIL import Image
+import style_inspect as inspector
+
+
+class StyleObservationTests(unittest.TestCase):
+ def setUp(self):
+ self.scratch = tempfile.TemporaryDirectory()
+ self.root = Path(self.scratch.name)
+
+ def tearDown(self):
+ self.scratch.cleanup()
+
+ def save(self, image, name="image.png", **kwargs):
+ path = self.root / name
+ image.save(path, **kwargs)
+ return path
+
+ def test_known_palette_coverage_and_source_identity(self):
+ image = Image.new("RGB", (20, 10), "white")
+ image.paste("red", (0, 0, 5, 10))
+ path = self.save(image)
+ result = inspector.inspect_image(path)
+ self.assertEqual(result["source_sha256"], hashlib.sha256(path.read_bytes()).hexdigest())
+ self.assertEqual({p["hex"]:p["fraction_of_included_samples"] for p in result["palette"]}, {"#FFFFFF":0.75,"#FF0000":0.25})
+ self.assertAlmostEqual(result["relative_luminance"]["mean"], 0.75 + 0.25 * 0.2126)
+
+ def test_roi_excludes_wrapper_pixels_and_bounds_are_relative(self):
+ image = Image.new("RGB", (100, 80), "black")
+ image.paste("white", (20, 10, 80, 70))
+ result = inspector.inspect_image(self.save(image), (20,10,60,60), (35,25,30,30))
+ self.assertEqual(result["palette"][0]["hex"], "#FFFFFF")
+ self.assertEqual(result["declared_subject"]["normalized_xywh_in_roi"], [0.25,0.25,0.5,0.5])
+ self.assertEqual(result["declared_subject"]["bounding_box_area_fraction"], 0.25)
+
+ def test_hidden_rgb_does_not_pollute_visible_palette(self):
+ image = Image.new("RGBA", (4, 1), (255,0,0,0))
+ image.putpixel((0,0), (0,0,255,255))
+ image.putpixel((1,0), (0,255,0,128))
+ result = inspector.inspect_image(self.save(image))
+ self.assertEqual(result["included_samples"],1)
+ self.assertEqual(result["partial_alpha_samples"],1)
+ self.assertEqual(result["palette"][0]["hex"],"#0000FF")
+
+ def test_explicit_matte_changes_appearance_with_recorded_policy(self):
+ path = self.save(Image.new("RGBA", (2,2), (255,0,0,0)))
+ result = inspector.inspect_image(path, matte="#FFFFFF")
+ self.assertEqual(result["palette"][0]["hex"],"#FFFFFF")
+ self.assertEqual(result["alpha_policy"],"encoded_RGB_composite")
+ self.assertEqual(result["included_samples"],4)
+
+ def test_all_transparent_image_has_no_invented_palette_or_luminance(self):
+ result=inspector.inspect_image(self.save(Image.new("RGBA",(2,2),(7,8,9,0))))
+ self.assertEqual(result["palette"],[])
+ self.assertIsNone(result["relative_luminance"]["mean"])
+
+ def test_exif_rotation_uses_display_coordinates(self):
+ exif=Image.Exif(); exif[274]=6
+ path=self.save(Image.new("RGB",(20,10),"white"),"rotated.jpg",exif=exif)
+ result=inspector.inspect_image(path, (0,0,10,20))
+ self.assertEqual(result["display_dimensions"],[10,20])
+ self.assertTrue(result["exif_orientation_normalized"])
+
+ def test_invalid_or_outside_rectangles_and_matte_fail(self):
+ path=self.save(Image.new("RGB",(20,20),"white"))
+ for kwargs in [{"roi":(-1,0,2,2)},{"roi":(0,0,0,1)},{"roi":(0,0,21,1)},{"roi":(True,0,2,2)},{"roi":(4,4,8,8),"subject":(0,0,2,2)},{"matte":"blue"}]:
+ with self.subTest(kwargs=kwargs), self.assertRaises(ValueError):
+ inspector.inspect_image(path,**kwargs)
+
+ def test_animation_is_not_silently_reduced_to_a_still(self):
+ path=self.save(Image.new("RGB",(4,4),"red"),"animated.webp",save_all=True,append_images=[Image.new("RGB",(4,4),"blue")],duration=100,loop=0)
+ with self.assertRaises(ValueError): inspector.inspect_image(path)
+
+ def test_sampling_is_bounded_and_deterministic(self):
+ path=self.save(Image.new("RGB",(2001,1103),"white"))
+ first=inspector.inspect_image(path)
+ self.assertLessEqual(first["sample_count"],inspector.MAX_SAMPLES)
+ self.assertEqual(first,inspector.inspect_image(path))
+
+ def test_existing_output_and_source_are_preserved(self):
+ path=self.save(Image.new("RGB",(4,4),"blue"))
+ output=self.root/"observations.json"; output.write_text("keep")
+ original=path.read_bytes()
+ with redirect_stderr(io.StringIO()):
+ self.assertEqual(inspector.main([str(path),"--out",str(output)]),1)
+ self.assertEqual(output.read_text(),"keep")
+ self.assertEqual(path.read_bytes(),original)
+
+ def test_failed_analysis_creates_no_output(self):
+ path=self.save(Image.new("RGB",(4,4),"blue"))
+ output=self.root/"observations.json"
+ with redirect_stderr(io.StringIO()):
+ self.assertEqual(inspector.main([str(path),"--roi","0","0","9","9","--out",str(output)]),1)
+ self.assertFalse(output.exists())
+
+ def test_large_dimension_limit_applies_before_pixel_analysis(self):
+ path=self.save(Image.new("RGB",(inspector.MAX_DIMENSION+1,1),"white"))
+ with self.assertRaises(ValueError): inspector.inspect_image(path)
+
+
+if __name__ == "__main__": unittest.main()
diff --git a/Editing_OS/Video Editing/Contracts/examples/production-context.v1.example.json b/Editing_OS/Video Editing/Contracts/examples/production-context.v1.example.json
index 8e9e14d..6834525 100644
--- a/Editing_OS/Video Editing/Contracts/examples/production-context.v1.example.json
+++ b/Editing_OS/Video Editing/Contracts/examples/production-context.v1.example.json
@@ -7,27 +7,27 @@
{
"role": "master_prompt",
"path": "Skills/MASTER_PROMPT.md",
- "sha256": "0f62e0c8fe668ade6502f2cc4eedc2cc622f82c9d3dd42d84d6b1b9946b8e164"
+ "sha256": "978d4e8a76dde8406e35c609c651e14b16ebd133bd398e596208ddb767c6f7fd"
},
{
"role": "taste_profile",
"path": "Skills/TASTE_PROFILE.md",
- "sha256": "c1e0d654dfd694f9f20cbf279491748a761becdc46bab36667316abcfb09c1dc"
+ "sha256": "2899765b6519ce26659e9fc666c37623dd760c4b79d94b0cb9b8d18b1335a12a"
},
{
"role": "tool_routing",
"path": "Skills/TOOL_ROUTING.md",
- "sha256": "36dcd8a41d2e7173b6f8e26cd2afa518149f5399d02754919a79ea868ae32474"
+ "sha256": "5106e13d6141755afb8acdd85cfd02b25104d1ced54919fecdaa11b8bfffe6da"
},
{
"role": "quality_standard",
"path": "Skills/QUALITY_STANDARD.md",
- "sha256": "9d0db6c34b856bd281521223a283d60e5c4bd06f9f40ef7bfa8a7098b38be024"
+ "sha256": "c37b18ddaa70c338eacc1644beed4feda29bc28e2b6762e6d8383bc122f4f1c2"
},
{
"role": "editing_handbook",
"path": "Skills/Video editing handbook/Elite_AI_Video_Editing_Workflow.md",
- "sha256": "ea0aa5f5511678fe04dd5dc2643b63f90994bd57450a3c6f70752152b0623949"
+ "sha256": "50a274ea6052be49baf5b589157bbb8c45288052945c15486bd02336b94d068f"
}
],
"operating_mode": "standard",
diff --git a/Editing_OS/runtime_paths.py b/Editing_OS/runtime_paths.py
index 79cdd55..1260f27 100644
--- a/Editing_OS/runtime_paths.py
+++ b/Editing_OS/runtime_paths.py
@@ -4,8 +4,8 @@
from pathlib import Path
class ConfigurationError(ValueError): pass
-TOOL_NAMES={'ffmpeg','ffprobe','node','hyperframes_cli','browser','gsap_runtime','inter_regular_font','inter_bold_font'}
-FILE_TOOLS={'hyperframes_cli','gsap_runtime','inter_regular_font','inter_bold_font'}
+TOOL_NAMES={'ffmpeg','ffprobe','node','hyperframes_cli','browser','gsap_runtime','inter_regular_font','inter_bold_font','three_module','puppeteer_entry'}
+FILE_TOOLS={'hyperframes_cli','gsap_runtime','inter_regular_font','inter_bold_font','three_module','puppeteer_entry'}
HYPERFRAMES_VERSION='0.8.146'
def contains(root,path):return path==root or root in path.parents
@@ -126,3 +126,15 @@ def model_environment():
w=workspace_root();cache=output(w/'dependencies/model-cache',require_workspace=True);cache.mkdir(parents=True,exist_ok=True)
for name,part in [('HF_HOME','huggingface'),('TORCH_HOME','torch')]:os.environ[name]=str(cache/part)
return cache
+
+
+def studio_resources():
+ module=Path(tool('three_module')).resolve()
+ package=module.parent.parent
+ try:info=json.loads((package/'package.json').read_text(encoding='utf-8'))
+ except (OSError,ValueError) as exc:raise ConfigurationError('Three.js package metadata missing') from exc
+ if info.get('name')!='three' or info.get('version')!='0.185.0' or module!=package/'build/three.module.js':raise ConfigurationError('Require exact external three@0.185.0 build/three.module.js')
+ paths={'three_module':module,'three_core':package/'build/three.core.js','room_environment':package/'examples/jsm/environments/RoomEnvironment.js'}
+ for name in ('gsap_runtime','inter_regular_font','inter_bold_font','puppeteer_entry','node','browser'):paths[name]=Path(tool(name)).resolve()
+ if not all(p.is_file() for p in paths.values()):raise ConfigurationError('Required 3D resource file missing')
+ return paths
diff --git a/LICENSE-SCOPE.md b/LICENSE-SCOPE.md
index e8e57e5..365fda8 100644
--- a/LICENSE-SCOPE.md
+++ b/LICENSE-SCOPE.md
@@ -7,3 +7,5 @@ The complete MIT text is in LICENSE. It covers owned Python/Lua/script code, tes
The complete CC BY 4.0 text is in LICENSE-DOCS. It covers all other owned explanatory Markdown, including component READMEs, the handbook, CLAIM_REGISTER, workbench GUIDE and these license/attribution explanations. Credit Editing-Pack by inisho2-byte, link the license, and identify changes as required by CC BY 4.0. Code snippets remain MIT.
Third-party components retain their own licenses; external tool entries are references, not relicensed source. No private projects, media, model weights, likenesses, trademarks or service outputs are licensed by this repository. Toolkit licenses do not impose a license on users' output videos. Contributions must be authorized and submitted under the applicable same scope.
+
+Owned JavaScript/HTML/CSS starter code, generated-example recipes and new Python helpers/tests are MIT. New specialist operational instructions are MIT; original handbook/provenance and explanatory guidance remain CC BY4.0 with MIT code snippets. Retained upstream notice texts keep their own terms. No tutorial transcript, source media, uncertain-license source or private approval is redistributed.
diff --git a/README.md b/README.md
index 46b7a93..dc3b43e 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
A source toolkit for AI-assisted video editing: an editing handbook, operating instructions, validated production contracts, Python engines and finishing tools. It is for editors and developers who want an inspectable workflow with explicit human decisions.
-**Status:** local prerelease candidate. A fresh Windows installation passes 184 core checks, or 213 with optional graphics. The offline synthetic walkthrough and browser-rendered drafts pass encoded decode and repeat comparisons. Real-production verification requires job-specific evidence. See the [verification scope](docs/verification.md). The toolkit is not a one-click native editor. See the [capability matrix](docs/capabilities.md) for tested features and limits.
+**Status:** v0.1.0-rc.1 is published; this source proposes v0.2.0-rc.1. The expanded candidate has 209 core checks and separate style, graphics and native 3D browser profiles. Final fresh-candidate verification and publication review are required before the proposed release. See the [verification scope](docs/verification.md) and [capability matrix](docs/capabilities.md). Real productions need job-specific evidence.
## Start here
@@ -10,6 +10,7 @@ A source toolkit for AI-assisted video editing: an editing handbook, operating i
2. Complete [getting started](docs/getting-started.md): diagnostics and synthetic contract validation, with no paid API or model download.
3. Run the [offline synthetic walkthrough](examples/synthetic-clock/README.md) to inspect timing, draft captions, encoded QA and gate refusals.
4. Read [architecture](docs/architecture.md), then the [production workflow](docs/workflow.md) before using your own footage.
+5. Choose a specialist in the [skill index](Editing_OS/Skills/README.md) and try the [generated-input examples](docs/new-capabilities.md).
After installation and local configuration, run these from the toolkit root:
diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md
index f0e581c..3f2b42e 100644
--- a/THIRD_PARTY_NOTICES.md
+++ b/THIRD_PARTY_NOTICES.md
@@ -5,3 +5,9 @@ This candidate includes owned source and no copied vendor runtime, font, icon, m
MIT: jsonschema, optional MCP SDK and the referenced Blender bridge, video-use, Whisper, voicebox, composition/toolkit references. Apache-2.0: HyperFrames, open-design and Playwright MCP root source. OpenMontage has AGPL-3.0 terms and stays external. WhisperX has BSD-2-Clause software terms; individual models are separate. GSAP uses custom Standard License terms and stays external. Inter uses OFL-1.1; known-source font provisioning and copyright/OFL retention are required. FFmpeg licensing depends on the selected build; no binaries are bundled.
If a later candidate includes third-party bytes, list their exact files and preserve the applicable full license/copyright/NOTICE text here or beside those files. The owned MIT/CC BY license does not replace upstream terms. No existing Windows font binaries are shipped.
+
+## New method references and optional resources
+
+The new recipes are original owned adaptations. Public revisions, exclusions and boundaries are listed in [PROVENANCE](Editing_OS/Skills/PROVENANCE.md) and the [3D source map](Editing_OS/Skills/studio-3d-objects/SOURCE_MAP.md). Preserve source credits: ACE-Step contributors, Bart (2026), Animate contributors and the respective public upstream authors. Their MIT notices are retained in notices/ where relevant; font/icon/model terms are separate and those assets are excluded. CloudAI-X content with unverified redistribution rights is not copied.
+
+Three.js0.185.0 is MIT; optional Puppeteer-core25.13.0 is Apache2.0. Optional Pillow12.3.0 uses MIT-CMU and separately licensed bundled components; obtain those notices with its external package. GSAP and Inter retain their existing custom/OFL notices. No installed resource is relicensed as toolkit MIT or handbook CC BY4.0. Runtime sites generated externally retain Three/GSAP/font notices and hashes.
diff --git a/config/candidate-status.json b/config/candidate-status.json
index 012175a..794b6fb 100644
--- a/config/candidate-status.json
+++ b/config/candidate-status.json
@@ -1,32 +1,22 @@
{
"schema": "editing-pack-candidate-status/v1",
- "stage": "clean-verified-local-candidate",
- "release_version": "0.1.0-rc.1",
- "publication_approved": false,
- "standalone_verified": true,
- "examples_are_synthetic": true,
+ "release_version": "0.2.0-rc.1",
+ "published_baseline": "0.1.0-rc.1",
+ "status": "proposed capability prerelease; final release review pending",
+ "publication_authorized": false,
+ "video_publication_authority": false,
+ "note": "Preparation snapshot. Release authorization is exact-candidate human review; per-video publication requires its own contract/evidence/review.",
+ "required_profiles": {
+ "core": 209,
+ "style-analysis": 12,
+ "graphics": 29,
+ "3d-browser": 1
+ },
"pending_steps": [
- 13,
- 14,
- 15,
- 16
- ],
- "core_setup_verified": true,
- "tested_platform": "Windows x64",
- "tested_python": "3.11.9",
- "owned_checks_passed": 213,
- "optional_limits": [
- "WhisperX/models not executed",
- "native project editing not verified",
- "real production source-to-final requires job-specific verification",
- "other operating systems/Python versions unverified",
- "tested Edge Windows version preflight failed"
- ],
- "documentation_verified": true,
- "synthetic_walkthrough_verified": true,
- "privacy_scan_completed": true,
- "export_negative_cases_verified": 27,
- "clean_environment_verified": true,
- "browser_render_verified": true,
- "tested_browser": "Chrome Headless Shell 152.0.7977.30"
+ "fresh-final-candidate verification",
+ "full privacy freeze",
+ "exact candidate approval",
+ "protected public PR/CI",
+ "tag and independent public verification"
+ ]
}
diff --git a/config/toolkit.example.json b/config/toolkit.example.json
index e329d21..cd87e3b 100644
--- a/config/toolkit.example.json
+++ b/config/toolkit.example.json
@@ -10,7 +10,9 @@
"browser": null,
"gsap_runtime": null,
"inter_regular_font": null,
- "inter_bold_font": null
+ "inter_bold_font": null,
+ "three_module": null,
+ "puppeteer_entry": null
},
"providers": {
"ideogram": {
diff --git a/config/tools.manifest.json b/config/tools.manifest.json
index 61e9dd2..4c68f3a 100644
--- a/config/tools.manifest.json
+++ b/config/tools.manifest.json
@@ -132,7 +132,7 @@
"role": "graphics animation runtime",
"distribution": "external-package-install",
"install": "Explicit pinned npm install --ignore-scripts outside toolkit; configure file paths. See docs/installation.md.",
- "compatibility": "Installed in isolated setup; owned graphics media/lint tests passed. Full public render workflow pending.",
+ "compatibility": "See docs/verification.md for dated evidence; final candidate and actual jobs need their own applicable checks.",
"package": "gsap",
"integrity": "sha512-dMW4CWBTUK1AEEDeZc1g4xpPGIrSf9fJF960qbTZmN/QwZIWY5wgliS6JWl9/25fpTGJrMRtSjGtOmPnfjZB+A==",
"asset_sha256": {
@@ -147,7 +147,7 @@
"role": "regular/bold graphics font resources",
"distribution": "external-package-install",
"install": "Explicit pinned npm install --ignore-scripts outside toolkit; configure file paths. See docs/installation.md.",
- "compatibility": "Installed in isolated setup; owned graphics media/lint tests passed. Full public render workflow pending.",
+ "compatibility": "See docs/verification.md for dated evidence; final candidate and actual jobs need their own applicable checks.",
"package": "@fontsource/inter",
"integrity": "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==",
"font_files": [
@@ -189,7 +189,7 @@
"role": "external media execution/probing",
"distribution": "external-install-only",
"install": "User-selected FFmpeg/FFprobe executable paths or PATH discovery.",
- "compatibility": "Source media tests used 9.0.2 full Windows build; public workflow verification pending."
+ "compatibility": "See docs/verification.md for dated evidence; final candidate and actual jobs need their own applicable checks."
},
{
"id": "jsonschema",
@@ -200,6 +200,37 @@
"distribution": "external-package-install",
"install": "requirements-core.lock.txt in separate environment",
"compatibility": "Windows x64 Python 3.11.9 isolated core checks passed."
+ },
+ {
+ "id": "three",
+ "version": "0.185.0",
+ "license": "MIT",
+ "role": "optional owned physical 3D runtime",
+ "distribution": "external-package-install",
+ "package": "three",
+ "integrity": "sha512-+yRrcRO2iZa8uzvNNl0d7cL4huhgKgBvVJ0njcTe8xFqZ6DMAFZdCKDP91SEAuj25bNAj7k1QQdf+srZywVK6w==",
+ "install": "Explicit exact npm install --ignore-scripts outside toolkit; see docs/installation.md.",
+ "compatibility": "Required browser profile; no implicit install or private asset discovery."
+ },
+ {
+ "id": "puppeteer-core",
+ "version": "25.13.0",
+ "license": "Apache-2.0",
+ "role": "optional native browser test client",
+ "distribution": "external-package-install",
+ "package": "puppeteer-core",
+ "integrity": "sha512-cyBS0OEx3e9NS53B5F6+UazXtR7f9Tw0cR1/FbPW59/hV6JPZbkIiMnxK2543IkFp3rsGlLn1iPDLF77TJsJsA==",
+ "install": "Explicit exact npm install --ignore-scripts outside toolkit; see docs/installation.md.",
+ "compatibility": "Required browser profile; no implicit install or private asset discovery."
+ },
+ {
+ "id": "pillow",
+ "version": "12.3.0",
+ "license": "MIT-CMU",
+ "role": "optional bounded image observations",
+ "distribution": "external-package-install",
+ "install": "requirements-style.lock.txt",
+ "compatibility": "Optional style profile; missing dependency fails explicitly."
}
]
}
diff --git a/docs/architecture.md b/docs/architecture.md
index 7068197..a431ed8 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -48,3 +48,14 @@ External tools remain separate processes/packages with their own terms. The tool
The handbook is a craft reference; active contracts define execution and publication. [Claim register](../Editing_OS/Skills/Evidence/CLAIM_REGISTER.md) qualifies timing, loudness, platform and style heuristics. Numeric defaults are review starting points unless the current delivery contract establishes them.
Some schema/evidence formats retain arete-prefixed identifiers for compatibility. These are contract identifiers, not a required remote service or private filesystem dependency.
+
+## Optional analysis and physical object layer
+
+Audio-reactive, motion-recipe, procedural-motion and studio-3d instructions live
+under the existing Skills root and load only for applicable work. `audio_motion`
+uses standard-library PCM/FFT analysis; `style_inspect` uses optional Pillow for
+bounded image observations. The owned Three.js starter provides absolute-time
+object scenes behind external, explicitly configured resources. Shared runtime
+guards keep analysis, test sites, caches and generated media outside source.
+These layers consume existing production contracts and never add a new approval
+authority or imply installation of studied vendor runtimes.
diff --git a/docs/capabilities.md b/docs/capabilities.md
index ddb4830..4df9759 100644
--- a/docs/capabilities.md
+++ b/docs/capabilities.md
@@ -26,8 +26,20 @@ Observed on Windows x64, CPython 3.11.9, FFmpeg/FFprobe 9.0.2 and Node.js 26.8.1
| Real production source-to-final | Unverified | Genuine alignment, selected treatment, approved cuts and exact-artifact human review required |
| Linux/macOS/other Python versions | Unverified | No cross-platform claim from this Windows observation |
-The core runner contains 184 checks. Optional graphics adds 29 for 213 total. Counts measure coverage, not production readiness. See [candidate status](../config/candidate-status.json).
+The expanded core runner contains 209 checks (including 9 audio checks). Style analysis adds 12, graphics adds 29 and the native 3D browser group adds one test containing 24 browser assertions, for 251 total enabled tests. Counts measure coverage, not production readiness. See [candidate status](../config/candidate-status.json).
## Expected human work
The editor defines goals/source permissions, reviews intent and cuts, selects treatment on real material, verifies native targets, inspects encoded output and signs the exact artifact review. Missing/stale evidence is rejected; these decisions are not silently completed.
+
+## New capability scope
+
+| Capability | Implemented scope | Limit |
+|---|---|---|
+| Offline audio motion | PCM identity, rational FPS, FFT bands and envelopes; 9 tests | No music generation, voice model or production alignment |
+| Style observations | Bounded ROI, palette, alpha and subject metrics; 12 optional tests | No inferred taste or automated human selection |
+| Native 3D starter | Owned hinge/object/material source, local dependencies and seek lifecycle; full-size software repeats matched | Software rendering is costly; fresh hardware repeat FAILED and is experimental |
+| Recipe/reference guidance | Four generic skill families and 118 bounded handbook techniques | Studying a technique or repository does not implement every native effect |
+
+See [verification](verification.md) for current release-gate evidence rather than
+treating historical v0.1 results as certification of changed code.
diff --git a/docs/configuration.md b/docs/configuration.md
index a23653b..11e5054 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -32,3 +32,12 @@ $ToolkitPython = '../editing-pack-env/Scripts/python.exe'
The doctor is diagnostic only. The launcher retains its graphical library and CLI modes; preview servers are foreground children owned by that launcher. Closing it or interrupting a CLI preview stops its owned process tree. It refuses an occupied port 3100. It does not reuse or stop another task's server, install HyperFrames, or register a sign-in task. Logs and process ownership records stay in workspace/cache. A bounded live preview check confirmed HTTP readiness and shutdown on the tested Windows setup; full UI editing/render verification remains pending.
Config files contain paths and environment variable references, never credentials or human approval. Synthetic context examples are fixtures, not approvals. Every real job hashes the current five governing documents and collects its own alignment, EDL, treatment, encoded QA and exact-artifact human review evidence.
+
+## New optional resource fields
+
+`tools.three_module` and `tools.puppeteer_entry` are explicit file paths for the
+native 3D browser profile. Existing configurations remain valid without these
+fields; enabling that profile requires them plus Node, browser, GSAP and Inter.
+The runtime derives matching Three core/addons from the exact installed package.
+Pillow is an optional Python profile, not a JSON tool path. Configuration never
+installs packages or supplies human authority. See [installation](installation.md).
diff --git a/docs/getting-started.md b/docs/getting-started.md
index b248be7..5500302 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -1,6 +1,6 @@
# Getting started
-This is the shortest verified core path: diagnose the setup and validate a synthetic contract. It does not require speech models, a native editor, a hosted image account or graphics packages. A rendered synthetic tutorial will be added in the examples step; a complete fresh production workflow is not yet certified.
+This is the shortest core path: diagnose the setup and validate a synthetic contract. It does not require speech models, a native editor, a hosted image account or graphics packages. The included synthetic clock tutorial renders a draft and tests authority refusals; real production workflows require their own evidence.
## 1. Prepare the three locations
@@ -35,7 +35,7 @@ Expected: exit 0 and `"valid": true`. This validates JSON shape and semantic rul
& $ToolkitPython -B scripts/run_checks.py --config config/toolkit.local.json
```
-Expected: each group reports `passed: true`, no skipped checks, exit 0. Core contains 184 checks; adding `--graphics` after optional graphics setup runs 213. Results/logs go in `workspace/cache/checks/`. Failures and skips are not successful verification. Test media is generated in external scratch, not taken from your projects.
+Expected: each group reports `passed: true`, no skipped checks, exit 0. Core contains 209 checks; style adds 12, graphics 29 and native 3D browser one test with 24 assertions. All profiles total 251. Results/logs go in `workspace/cache/checks/`. Failures and skips are not successful verification. Test media is generated in external scratch, not taken from your projects.
## 5. Run the offline draft walkthrough
@@ -46,3 +46,12 @@ Follow the [synthetic clock tutorial](../examples/synthetic-clock/README.md). It
Read [architecture](architecture.md), [capabilities](capabilities.md) and [workflow](workflow.md). Load [START_HERE](../Editing_OS/Skills/START_HERE.md) before directing an editing agent. Keep the real brief, media, contracts and evidence in a new external job folder. Do not copy synthetic approvals into it.
For captions from audio, inspect [alignment setup](optional-tools.md#alignment-and-models) before installing heavy dependencies. Graphics needs the explicit pinned resources. You can work with supplied genuine aligned words without invoking local transcription.
+
+## Explore the new specialists
+
+The published baseline includes the synthetic clock tutorial. This update adds
+four [specialist families](../Editing_OS/Skills/README.md) and [generated PCM,
+palette and 3D examples](new-capabilities.md). Start with offline PCM, install
+Pillow for palette analysis, then explicitly provision the 3D/browser resources.
+Expected results and failure diagnostics are documented with those examples.
+All generated jobs are external drafts; none supplies publication approval.
diff --git a/docs/installation.md b/docs/installation.md
index d943778..59ed27a 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -1,6 +1,6 @@
# Installation
-This candidate is being prepared for release. The tested setup is Windows x64 with Python 3.11.9; other platforms still require fresh verification. Core tooling is installed separately from optional editors, models and graphics packages. Keep the toolkit checkout, dependencies and job workspace in separate folders.
+The published baseline is v0.1.0-rc.1; this update proposes v0.2.0-rc.1. The tested setup is Windows x64 with Python 3.11.9; other platforms still require fresh verification. Core tooling is installed separately from optional editors, models and graphics packages. Keep the toolkit checkout, dependencies and job workspace in separate folders.
## Core (PowerShell)
@@ -56,3 +56,21 @@ Ideogram execution requires the `IDEOGRAM_API_KEY` environment variable and the
The Resolve mailbox/MCP integration is a guarded prototype, not a complete native editor. Install `requirements-resolve.lock.txt` into a separate environment only if you need it. Configure a mailbox inside the workspace and supply `EDITING_PACK_RESOLVE_MAILBOX`, `EDITING_PACK_RESOLVE_PROJECT_ID` and `EDITING_PACK_RESOLVE_PROJECT_NAME` to the Lua/native application process too. JSON config cannot configure another process automatically. The bridge requires an exact empty test project and preserves write/readback/cleanup guards. No native application is opened by the check runner. Premiere and Final Cut remain conditional on installed application APIs/DTDs; CapCut native interchange is not implemented.
Third-party specialist clones are optional, externally installed tools. They are not copied into this repository and do not grant Editing OS production authority.
+
+## Optional style analysis and native 3D browser profiles
+
+```powershell
+../editing-pack-env/Scripts/python.exe -m pip install --only-binary=:all: -r requirements-style.lock.txt
+npm install --prefix ../editing-pack-graphics --ignore-scripts --no-audit --no-fund --save-exact three@0.185.0 puppeteer-core@25.13.0
+../editing-pack-env/Scripts/python.exe -B scripts/run_checks.py --config config/toolkit.local.json --style-analysis --graphics --3d-browser
+```
+
+Pillow 12.3.0 is optional; core/audio checks do not need it. Use the graphics setup
+above first. Add `tools.three_module` pointing to
+`node_modules/three/build/three.module.js` and `tools.puppeteer_entry` pointing to
+`node_modules/puppeteer-core/lib/puppeteer/puppeteer-core.js`. The runtime requires
+Three 0.185.0 and derives its matching core/addon files; retain package metadata
+and licenses. Puppeteer 25 uses this entry rather than the older lib/cjs path.
+Configured Node and browser paths must be executable files. No native Blender,
+segmentation model or vendor clone is installed by this profile. See the
+[new examples](new-capabilities.md) and [verification](verification.md).
diff --git a/docs/maintenance.md b/docs/maintenance.md
index 61cc5dc..10c9a3c 100644
--- a/docs/maintenance.md
+++ b/docs/maintenance.md
@@ -12,7 +12,7 @@ Preserve reusable source/private job separation. Read [contributing](../CONTRIBU
## Version practice
-Maintain [CHANGELOG](../CHANGELOG.md)'s Unreleased section. Choose/approve the first version during release review; this candidate has none. Use semantic versions later: patch for compatible fixes, minor for compatible capabilities, major for incompatible public CLI/config/schema behavior. Production schema versions are separate contracts; do not change v1 incompatibly in place.
+Maintain [CHANGELOG](../CHANGELOG.md)'s Unreleased section. The published baseline is v0.1.0-rc.1; this update proposes v0.2.0-rc.1, subject to exact-candidate release review. Use patch versions for compatible fixes, minor versions for compatible capabilities and major versions for incompatible public CLI/config/schema behavior. Production schema versions are separate contracts; do not change v1 incompatibly in place.
Update `toolkit.json` release_version and candidate status only to describe the actual approved release. Tests are not publication permission. Release notes identify tested platforms, validation, migration and limits.
diff --git a/docs/new-capabilities.md b/docs/new-capabilities.md
new file mode 100644
index 0000000..06d6660
--- /dev/null
+++ b/docs/new-capabilities.md
@@ -0,0 +1,56 @@
+# Generated-input capability examples
+
+Run from the toolkit root after [installation](installation.md) and external
+[configuration](configuration.md). Keep each new job name unique. Every example
+requires explicit draft consent and writes only to `workspace_root/jobs/`.
+No real footage, speech, approvals or downloaded reference media is used.
+
+```powershell
+$ToolkitPython = '../editing-pack-env/Scripts/python.exe'
+$Examples = 'Editing_OS/Tools/editing-workbench/capability_examples.py'
+& $ToolkitPython -B $Examples --config config/toolkit.local.json audio --job-name pcm-demo --allow-unapproved-draft-treatment
+& $ToolkitPython -B $Examples --config config/toolkit.local.json style --job-name palette-demo --allow-unapproved-draft-treatment
+& $ToolkitPython -B $Examples --config config/toolkit.local.json studio --job-name object-demo --allow-unapproved-draft-treatment --render --capture software
+```
+
+The audio example generates two seconds of mono 16 kHz signed 16-bit PCM: one
+second at 440 Hz, then one at 880 Hz. `evidence/audio-motion.json` has 60 frame
+samples at 30000/1001 fps, source SHA, frequency bands, RMS/peak and bounded
+attack/release envelopes. The dominant bands shift with frequency. For motion,
+index this frozen array from absolute output time; never integrate mutable live
+audio state. Analysis itself is not an encoded visualizer. Placement starts at
+zero here; real edited audio must use its final placement and retimed timeline.
+
+The optional style example generates a 160 by 100 opaque RGBA palette. It inspects
+ROI `[20,20,120,60]` and subject `[20,20,50,60]`; the subject is cyan and the ROI
+also contains amber and dark background. `evidence/style-observations.json`
+records bounded image geometry, palette/alpha and source identity. Pixel
+observations do not infer artistic intent or choose a treatment. `--render` is
+refused for audio/style because these commands create analysis fixtures.
+
+The studio example generates a three-second 1080 by 1920 draft with physical
+folder/cards, hinge motion, lighting and shadows. It stages configured Three.js,
+GSAP and Inter resources into the external job, with notices and hashes. It
+checks readiness at three times, renders with one software worker, and decodes
+the MP4 through the Quality engine. `ready` and `publication_approved` remain
+false. Software rendering is expensive; allow several minutes for this short
+full-size scene. Hardware capture is experimental: the fresh independent hardware
+repeat differed and cannot satisfy a deterministic production gate.
+
+Use `--example` to choose `folder-cards-rise`, `cards-scatter-file-in`,
+`mat-loupe-stamp`, `monitor-timeline` or `tablet-over-footage`. The last example
+uses a generated abstract background rather than real footage. Without `--render`
+the command prepares source only. Missing resources fail before job creation;
+existing jobs are never overwritten. Failed later rendering retains diagnostics
+under `cache`, and must not be reported as a successful demo.
+
+```powershell
+& $ToolkitPython -B scripts/run_checks.py --config config/toolkit.local.json --style-analysis --graphics --3d-browser
+```
+
+The browser profile exercises forward/backward/random seeks, A-B-A and shuffled
+repeat snapshots, resource failures, host offsets, shared resource disposal,
+readiness and nonblank frames. Required enabled profiles refuse missing tools,
+skips and zero tests. See [verification](verification.md) for current evidence.
+The [synthetic clock](../examples/synthetic-clock/README.md) remains the timing
+and gate-refusal tutorial. No fixture produces a human publication approval.
diff --git a/docs/optional-tools.md b/docs/optional-tools.md
index 6e2ce12..9566d7d 100644
--- a/docs/optional-tools.md
+++ b/docs/optional-tools.md
@@ -41,3 +41,14 @@ Do not run the connection test in a real working project. Its create/readback/de
The manifest references video-use, open-design, voicebox, OpenMontage, Playwright MCP and composition toolkits. Follow pinned upstream setup externally and retain their licenses/notices. OpenMontage's AGPL terms remain separate. Optional scheduling cannot replace the adapter's contracts or Quality readiness.
See [third-party notices](../THIRD_PARTY_NOTICES.md) and [capabilities](capabilities.md).
+
+## Analysis and physical-object resources
+
+Pillow 12.3.0 adds bounded image analysis. Three.js 0.185.0 and puppeteer-core
+25.13.0 add the owned starter/browser regression profile alongside configured
+HyperFrames 0.8.146, GSAP 3.15.0, Inter 5.2.8 and Chrome Headless Shell. Explicit
+external installation commands are in [installation](installation.md). Three
+and Puppeteer are MIT/Apache-2.0 respectively; GSAP has its own custom license
+and Inter remains OFL. Installed assets are staged only into external jobs.
+The nine studied 3D/web repositories are references, not installed integrations;
+see [provenance](../Editing_OS/Skills/PROVENANCE.md).
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
index e7ceb59..1cea9b6 100644
--- a/docs/troubleshooting.md
+++ b/docs/troubleshooting.md
@@ -37,3 +37,18 @@ $ToolkitPython = '../editing-pack-env/Scripts/python.exe'
```
A [public bug report](../.github/ISSUE_TEMPLATE/bug_report.md) needs revision, platform/Python, tool versions, expected/actual results and a synthetic reproduction. Security/private data uses [SECURITY](../SECURITY.md).
+
+## New profile diagnostics
+
+- Missing Pillow: install `requirements-style.lock.txt` in the selected Python
+ environment; do not add it to core just to conceal a missing optional profile.
+- Missing Three/core/addon: configure the full pinned Three 0.185.0 package, not
+ one copied module. Missing Puppeteer: use the documented version-25 entry.
+- Blank scene or missing required asset: inspect external job/cache logs and
+ readiness. Never replace failure with a silent screenshot or fallback asset.
+- Existing demo job: choose a new job name; the example refuses overwrite.
+- Audio/style `--render`: these create analysis fixtures; rendering is supported
+ only for studio. Follow [example expectations](new-capabilities.md).
+- Slow software 3D: a full-size three-second render can take several minutes.
+ Hardware throughput does not prove decoded repeatability; record independent
+ repeat results for each actual profile and keep failed evidence visible.
diff --git a/docs/verification.md b/docs/verification.md
index f20092e..c71a3f3 100644
--- a/docs/verification.md
+++ b/docs/verification.md
@@ -1,4 +1,59 @@
-# Fresh-install verification
+# Verification evidence and release gates
+
+## Expanded candidate — 2026-10-14
+
+The proposed v0.2.0-rc.1 candidate has passed 251 tests in a fresh anonymous-base
+clone plus reviewed local payload, a new Python environment, newly installed
+pinned packages, new user/browser profile and external workspace with spaces.
+No skips or zero-test groups passed. Python access to original private sources,
+skill stores and the earlier preparation environment was denied. This is one
+Windows host, not an independent VM or a Node/browser security sandbox.
+
+| Profile | Tests | Requirement |
+|---|---:|---|
+| Core | 209 | Locked core Python packages, FFmpeg/FFprobe |
+| Style analysis | 12 | Optional pinned Pillow 12.3.0 |
+| Graphics | 29 | Configured pinned HyperFrames, GSAP and Inter |
+| Native 3D browser | 1, with 24 browser assertions | Configured Three 0.185.0, Puppeteer 25.13.0, Node and browser |
+
+The core-only environment separately passed all 209 checks with no Pillow
+installed. The synthetic clock and generated PCM/palette examples also pass in that
+environment. The 3D profile verifies SwiftShader identity, nonblank frames,
+A-B-A/shuffled seeking, lifecycle/disposal, live offsets and failed required
+dependencies/fonts. Two fresh full-size software renders decoded identically at
+1080 by 1920, 30 fps/three seconds, with no audio. The first took 296 seconds
+including checks/QA; the repeat render took 235 seconds. Frames at 0.4, 1.5 and
+2.6 seconds were inspected for actual folder/cards, readable draft labels,
+lighting and shadows. This inspection is not human production review.
+
+Hardware renders took about 19 seconds each and decoded successfully, but their
+decoded video fingerprints differed. Hardware repeatability therefore FAILED;
+hardware is experimental and cannot satisfy a deterministic production gate.
+No waiver is applied. Software repeatability is the verified profile for this
+synthetic scene, not a guarantee for arbitrary projects.
+
+Tested resources: CPython 3.11.9, Node 26.8.1, FFmpeg/FFprobe 9.0.2, Chrome for
+Testing 152.0.7977.30, HyperFrames 0.8.146, Three 0.185.0, Puppeteer 25.13.0,
+GSAP 3.15.0, Inter 5.2.8 and Pillow 12.3.0. Task-owned rendering/browser processes
+were checked after completion; none remained.
+
+The [CI workflow](../.github/workflows/core.yml) runs core plus style (221 tests),
+the synthetic walkthrough, dependency consistency, local source/link checks and
+checksum-pinned Gitleaks. Actions remain commit-pinned, read-only, with no
+persisted credentials, provider keys, private media, publication or artifact
+upload. Graphics and native browser/encoded repeats are a mandatory manual local
+release gate using all profiles and the documented examples; CI core/style alone
+does not verify them. Any candidate change invalidates its freeze and requires
+affected checks; final public CI and anonymous downloads are checked after the
+exact candidate is approved and uploaded.
+
+Hardware repeat failure from earlier private diagnostic work remains a known
+limit. Hardware speed does not confer deterministic rendering. No production
+waiver is invented. Native editors, paid calls, speech models and other operating
+systems remain conditional or unverified. Every synthetic draft remains unready
+for publication and never supplies a human approval.
+
+## Published v0.1.0-rc.1 historical verification
Verified on 2026-10-11 in a new local checkout, Python environment, external workspace and user profile. Direct Python access to the original private workspace, vendor clones and prior developer environments was denied during the checks. This is filesystem/configuration isolation on one Windows host, not an independent operating-system VM or a Node/browser security sandbox.
@@ -24,6 +79,6 @@ Live WhisperX/model alignment, GPU workflows, paid provider execution, native ed
Private verification logs, media, local paths and configuration are excluded from this repository. This local verification does not authorize uploading the release candidate; public-clone verification follows publication.
-## Prepared CI
+### First-release CI
-The [Windows workflow](../.github/workflows/core.yml) runs locked core dependency checks, [source/link inspection](../scripts/check_source.py), checksum-pinned Gitleaks, the 184 core checks and the synthetic walkthrough. Actions are pinned by commit; permissions are read-only and checkout credentials are not persisted. It uses hosted Windows runners with external temporary dependencies/workspaces and no provider keys or private media. Fork pull requests use `pull_request`, never `pull_request_target`; no publication or artifact-upload step is included. Optional browser graphics are covered by local verification, not this core workflow. Local workflow commands are checked before candidate review; a real GitHub Actions run remains pending upload.
+The first release's protected PR and three GitHub CI runs passed. Its workflow ran 184 core checks, synthetic media and source/privacy checks. The expanded candidate changes the profile count as described above; first-release CI does not certify new files. Fork PR execution remains `pull_request`, never `pull_request_target`.
diff --git a/docs/workflow.md b/docs/workflow.md
index 5488c71..b6eda2f 100644
--- a/docs/workflow.md
+++ b/docs/workflow.md
@@ -85,3 +85,14 @@ This prints a template, not approval. Feed completed review and required evidenc
## When something changes
Changing cuts invalidates dependent timing/caption/graphics evidence. Changing treatment requires renewed selection and dependent render evidence. Changing export bytes requires matching fresh encoded QA and human review. Correct mismatches rather than carrying old approvals forward.
+
+## Motion and reference handoffs
+
+Use the [skill index](../Editing_OS/Skills/README.md) to choose applicable craft.
+Freeze final audio placement before computing frame-indexed motion observations;
+index them from absolute output time. Image palette/ROI measurements guide option
+preparation and cannot choose taste. Physical 3D scenes require dependency-ready
+seeking and encoded repeat checks for the claimed capture profile. Keep genuine
+forced alignment, approved EDL, retimed words, explicit treatment and exact-artifact
+human review at the existing seams. A toolkit release is distinct from publishing
+a video produced with it.
diff --git a/notices/ACE-Step-MIT.txt b/notices/ACE-Step-MIT.txt
new file mode 100644
index 0000000..600451d
--- /dev/null
+++ b/notices/ACE-Step-MIT.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 ACEStep
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/notices/Animate-MIT.txt b/notices/Animate-MIT.txt
new file mode 100644
index 0000000..1c767b1
--- /dev/null
+++ b/notices/Animate-MIT.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 cth9191
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/notices/Barty-Bart-MIT.txt b/notices/Barty-Bart-MIT.txt
new file mode 100644
index 0000000..5088d7b
--- /dev/null
+++ b/notices/Barty-Bart-MIT.txt
@@ -0,0 +1,25 @@
+MIT License
+
+Copyright (c) 2026 Bart
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+The Geist and Geist Mono fonts in skills/motion-broll/engine/fonts are
+licensed separately under the SIL Open Font License 1.1 (see OFL-Geist.txt).
+Icon paths are adapted from Lucide (ISC License).
diff --git a/requirements-style.lock.txt b/requirements-style.lock.txt
new file mode 100644
index 0000000..e7cc6c1
--- /dev/null
+++ b/requirements-style.lock.txt
@@ -0,0 +1 @@
+Pillow==12.3.0
diff --git a/requirements-style.txt b/requirements-style.txt
new file mode 100644
index 0000000..5a306e1
--- /dev/null
+++ b/requirements-style.txt
@@ -0,0 +1,2 @@
+# Optional image observations; core remains independent of Pillow.
+Pillow==12.3.0
diff --git a/scripts/export_release.py b/scripts/export_release.py
index 4ecf5e9..6dea407 100644
--- a/scripts/export_release.py
+++ b/scripts/export_release.py
@@ -9,11 +9,14 @@
from pathlib import Path,PurePosixPath
class ExportError(ValueError): pass
-ALLOWED={'.md','.py','.json','.txt','.lua','.toml','.yml','.yaml','.ps1','.sh'}
+ALLOWED={'.md','.py','.json','.txt','.lua','.toml','.yml','.yaml','.ps1','.sh','.js','.html','.css'}
SPECIAL={'LICENSE','LICENSE-DOCS','.gitignore','.gitattributes','.env.example'}
BLOCKED={'.git','.venv','venv','node_modules','__pycache__','videos','projects','assets','archive','audits','case studies','working_mem','.claude','.codex','personal projects','client projects',
'jobs','inputs','outputs','exports','renders','work','workspace','workspaces','cache','.cache','logs','dependencies','.idea','.vscode','.hyperframes'}
def digest(p): return hashlib.sha256(p.read_bytes()).hexdigest()
+def public_content(text):
+ if re.search(r'(?i)(?:[A-Z]:[/\\]+Users[/\\]+|file:' + r'//|Project wiki[/\\])', text):
+ raise ExportError('Embedded private/local locator is not public source')
def inside(p,r): return p==r or r in p.parents
def no_links(p):
for x in [p,*p.parents]:
@@ -59,7 +62,7 @@ def git(*args):return subprocess.check_output(['git','-C',str(dst),*args],stderr
if not source.is_file() or not inside(source.resolve(),src):raise ExportError('Source outside payload')
b=source.read_bytes()
if len(b)>2_000_000 or b'\0' in b or b.startswith((b'PK\x03\x04',b'\x1f\x8b')):raise ExportError('Binary/archive/oversize content')
- try:b.decode('utf-8')
+ try:public_content(b.decode('utf-8'))
except UnicodeError as e:raise ExportError('Non-UTF8 content') from e
if digest(source)!=entry['sha256']:raise ExportError('Payload hash mismatch')
if target.exists() and (not target.is_file() or digest(target) not in {entry['sha256'],expected_existing.get(str(q))}):raise ExportError('Unexpected destination file content')
diff --git a/scripts/run_checks.py b/scripts/run_checks.py
index 9824750..5e906f6 100644
--- a/scripts/run_checks.py
+++ b/scripts/run_checks.py
@@ -6,20 +6,22 @@
import runtime_paths as runtime
GROUPS=[('contracts','Editing_OS/Video Editing/Contracts',23),('adapter','Editing_OS/Video Editing/Engines/Orchestration_adapter',8),('captions','Editing_OS/Video Editing/Engines/Captions_engine',39),('editorial','Editing_OS/Video Editing/Engines/Video editing engine',37),('quality','Editing_OS/Video Editing/Engines/Quality_engine',29),('photo','Editing_OS/Photo editing/Engines/Ideogram4_engine',12),('workbench','Editing_OS/Tools/editing-workbench',17)]
def main():
- p=argparse.ArgumentParser(description=__doc__);runtime.common_args(p);p.add_argument('--graphics',action='store_true');a=p.parse_args()
+ p=argparse.ArgumentParser(description=__doc__);runtime.common_args(p);p.add_argument('--graphics',action='store_true');p.add_argument('--style-analysis',action='store_true');p.add_argument('--3d-browser',dest='studio',action='store_true');a=p.parse_args()
runtime.configure_args(a);root=runtime.root();w=runtime.workspace_root();runtime.tool('ffmpeg');runtime.tool('ffprobe')
if a.graphics:runtime.hyperframes_command([]);[runtime.tool(x) for x in ('gsap_runtime','inter_regular_font','inter_bold_font')]
+ if a.studio:runtime.studio_resources()
scratch=runtime.output(w/'cache/checks',require_workspace=True);scratch.mkdir(parents=True,exist_ok=True)
env=runtime.child_env();env.update(TEMP=str(scratch),TMP=str(scratch),TMPDIR=str(scratch));results=[]
- groups=[*GROUPS,('runtime','tests',0)]+([('graphics','Editing_OS/Video Editing/Engines/Graphics_engine',29)] if a.graphics else [])
+ groups=[*GROUPS[:-1],('workbench','Editing_OS/Tools/editing-workbench',14),('inventory','Editing_OS/Tools/editing-workbench',3),('runtime','tests',19),('exporter','tests',10),('helper-boundaries','tests',6),('audio','Editing_OS/Tools/editing-workbench',9)]+([('style','Editing_OS/Tools/editing-workbench',12)] if a.style_analysis else [])+([('graphics','Editing_OS/Video Editing/Engines/Graphics_engine',29)] if a.graphics else [])+([('3d-browser','Editing_OS/Tools/editing-workbench',1)] if a.studio else [])
+ patterns={'workbench':'test_workbench.py','inventory':'test_inventory.py','runtime':'test_runtime_paths.py','exporter':'test_exporter.py','helper-boundaries':'test_helper_boundaries.py','audio':'test_audio_motion.py','style':'test_style_inspect.py','3d-browser':'test_studio3d.py'}
for name,folder,expected in groups:
- cmd=[sys.executable,'-B','test_engine.py'] if name=='captions' else [sys.executable,'-B','-m','unittest','discover','-s','tests' if name=='contracts' else '.', '-p','test*.py','-v']
+ cmd=[sys.executable,'-B','test_engine.py'] if name=='captions' else [sys.executable,'-B','-m','unittest','discover','-s','tests' if name=='contracts' else '.', '-p',patterns.get(name,'test*.py'),'-v']
r=subprocess.run(cmd,cwd=root/folder,env=env,capture_output=True,text=True,encoding='utf-8',errors='replace',timeout=300,**runtime.child_kwargs())
output=r.stdout+r.stderr;(scratch/(name+'.log')).write_text(output,encoding='utf-8');m=re.search(r'Ran (\d+) tests?',output) if name!='captions' else re.search(r'(\d+)/39 passed',output)
count=int(m.group(1)) if m else 0;skipped='skipped=' in output or '... skipped' in output
passed=r.returncode==0 and count>0 and (count==expected if expected else True) and not skipped
results.append({'group':name,'tests':count,'exit_code':r.returncode,'skipped':skipped,'passed':passed});print(json.dumps(results[-1]),flush=True)
- report={'schema':'editing-pack-checks/v1','passed':all(x['passed'] for x in results),'groups':results,'publication_approval':False};(scratch/'results.json').write_text(json.dumps(report,indent=2),encoding='utf-8');return 0 if report['passed'] else 1
+ report={'schema':'editing-pack-checks/v1','passed':all(x['passed'] for x in results),'groups':results,'publication_approval':False,'profiles':{'core':True,'style-analysis':a.style_analysis,'graphics':a.graphics,'3d-browser':a.studio},'total_tests':sum(x['tests'] for x in results)};(scratch/'results.json').write_text(json.dumps(report,indent=2),encoding='utf-8');return 0 if report['passed'] else 1
if __name__=='__main__':
try:raise SystemExit(main())
except (ValueError,OSError,subprocess.TimeoutExpired) as exc:print('Setup/check failure: '+str(exc),file=sys.stderr);raise SystemExit(2)
diff --git a/tests/test_exporter.py b/tests/test_exporter.py
new file mode 100644
index 0000000..1e9896c
--- /dev/null
+++ b/tests/test_exporter.py
@@ -0,0 +1,151 @@
+"""MIT. Export privacy gates using isolated fictional repositories, never user projects."""
+import hashlib
+import importlib.util
+import json
+import os
+from pathlib import Path
+import subprocess
+import tempfile
+import unittest
+
+spec = importlib.util.spec_from_file_location('release_export', Path(__file__).parents[1] / 'scripts/export_release.py')
+exporter = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(exporter)
+
+
+class ExportPrivacyTests(unittest.TestCase):
+ def setUp(self):
+ self.temp = tempfile.TemporaryDirectory(prefix='export-gate-')
+ self.addCleanup(self.temp.cleanup)
+ self.root = Path(self.temp.name)
+ self.payload = self.root / 'payload'
+ self.dst = self.root / 'checkout'
+ self.protected = self.root / 'protected'
+ for p in (self.payload, self.dst, self.protected):
+ p.mkdir()
+ self.env = os.environ.copy()
+ self.env.update(GIT_CONFIG_GLOBAL='NUL' if os.name == 'nt' else '/dev/null', GIT_CONFIG_NOSYSTEM='1')
+ self.git('-c', 'init.defaultBranch=main', 'init')
+ (self.dst / 'README.md').write_text('# Fixture baseline\n', encoding='utf-8')
+ self.git('add', 'README.md')
+ self.git('-c', 'user.name=Fixture', '-c', 'user.email=fixture@example.com', '-c', 'commit.gpgsign=false', 'commit', '-m', 'Fictional baseline')
+ self.origin = 'https://github.com/inisho2-byte/Editing-Pack.git'
+ self.git('remote', 'add', 'origin', self.origin)
+ self.git('remote', 'set-url', '--push', 'origin', 'disabled://test-only')
+ self.manifest = self.root / 'manifest.json'
+ self.report = self.root / 'report.json'
+ self.data = {'schema': 'editing-pack-export/v1', 'payload_root': str(self.payload),
+ 'protected_roots': [str(self.protected)], 'expected_origin': self.origin,
+ 'baseline_commit': self.git('rev-parse', 'HEAD').strip(),
+ 'baseline_files': {'README.md': exporter.digest(self.dst / 'README.md')}, 'files': []}
+ self.add('README.md', '# Fixture update\n')
+
+ def git(self, *args):
+ r = subprocess.run(['git', '-C', str(self.dst), *args], env=self.env, capture_output=True,
+ text=True, creationflags=getattr(subprocess, 'CREATE_NO_WINDOW', 0) if os.name == 'nt' else 0)
+ self.assertEqual(r.returncode, 0, r.stderr)
+ return r.stdout
+
+ def add(self, name, text):
+ p = self.payload / name
+ p.parent.mkdir(parents=True, exist_ok=True)
+ p.write_text(text, encoding='utf-8', newline='\n')
+ self.data['files'].append({'source': name, 'destination': name,
+ 'sha256': exporter.digest(p), 'bytes': p.stat().st_size})
+
+ def run_export(self, apply=False):
+ self.manifest.write_text(json.dumps(self.data), encoding='utf-8')
+ return exporter.run(self.manifest, self.dst, self.report, apply)
+
+ def refusal(self):
+ before = (self.dst / 'README.md').read_bytes()
+ with self.assertRaises(exporter.ExportError):
+ self.run_export(True)
+ self.assertEqual((self.dst / 'README.md').read_bytes(), before)
+
+ def test_explicit_web_source_dry_run_apply_and_resume(self):
+ for name, text in [('starter/scene.js', 'export const state = 1;\n'),
+ ('starter/index.html', 'Draft fixture
\n'),
+ ('starter/stage.css', '.draft {color: black}\n')]:
+ self.add(name, text)
+ self.assertEqual(self.run_export()['mode'], 'dry-run')
+ self.assertFalse((self.dst / 'starter/scene.js').exists())
+ for _ in range(2):
+ self.assertEqual(self.run_export(True)['files'], 4)
+ self.assertFalse(json.loads(self.report.read_text())['publication_approved'])
+
+ def test_relative_traversal_absolute_reserved_and_local_names(self):
+ for value in ['../out.js', '/out.html', 'a/../out.css', 'a\\out.js', 'CON.js', 'a/toolkit.local.json']:
+ with self.subTest(value=value), self.assertRaises(exporter.ExportError):
+ exporter.relative(value)
+
+ def test_unknown_source_and_destination_files_refuse_before_writes(self):
+ (self.payload / 'extra.js').write_text('unknown')
+ self.refusal()
+ (self.payload / 'extra.js').unlink()
+ (self.dst / 'extra.html').write_text('unknown')
+ self.refusal()
+
+ def test_binary_media_private_categories_and_oversize_refused(self):
+ for value in ['jobs/draft.html', 'projects/scene.js', 'dependencies/library.js', 'clip.mp4', 'archive.zip']:
+ with self.subTest(value=value), self.assertRaises(exporter.ExportError):
+ exporter.relative(value)
+ for data in [b'\x00', b'PK\x03\x04payload', b'x' * 2_000_001]:
+ p = self.payload / 'README.md'
+ p.write_bytes(data)
+ self.data['files'][0].update(sha256=exporter.digest(p), bytes=len(data))
+ self.refusal()
+
+ def test_embedded_machine_paths_refused_in_web_types(self):
+ for name in ['scene.js', 'index.html', 'stage.css']:
+ for value in ['C:' + '/Users/Fixture/private', 'file:' + '//private/fixture']:
+ with self.subTest(name=name, value=value):
+ self.add(name, value)
+ self.refusal()
+ self.data['files'].pop()
+ (self.payload / name).unlink()
+
+ def test_stale_source_hash_and_baseline_refused(self):
+ original = dict(self.data['files'][0])
+ self.data['files'][0]['sha256'] = '0' * 64
+ self.refusal()
+ self.data['files'][0] = original
+ self.data['baseline_commit'] = '0' * 40
+ self.refusal()
+
+ def test_wrong_origin_and_enabled_push_refused(self):
+ self.git('remote', 'set-url', 'origin', 'https://example.com/wrong.git')
+ self.refusal()
+ self.git('remote', 'set-url', 'origin', self.origin)
+ self.git('remote', 'set-url', '--push', 'origin', self.origin)
+ self.refusal()
+
+ def test_protected_overlap_and_internal_manifest_refused(self):
+ self.data['protected_roots'] = [str(self.dst)]
+ self.refusal()
+ self.data['protected_roots'] = [str(self.protected)]
+ self.manifest = self.payload / 'manifest.json'
+ self.refusal()
+
+ def test_windows_junction_or_posix_link_rejected_without_reading_target(self):
+ target = self.root / 'private fixture'
+ target.mkdir()
+ link = self.payload / 'linked'
+ if os.name == 'nt':
+ import _winapi
+ _winapi.CreateJunction(str(target), str(link))
+ else:
+ link.symlink_to(target, target_is_directory=True)
+ self.addCleanup(lambda: link.rmdir() if os.name == 'nt' else link.unlink())
+ self.refusal()
+
+ def test_partial_interruption_only_identical_manifested_writes_resume(self):
+ self.add('starter/scene.js', 'export const fixture = true;\n')
+ (self.dst / 'README.md').write_bytes((self.payload / 'README.md').read_bytes())
+ self.assertEqual(self.run_export(True)['files'], 2)
+ (self.dst / 'starter/scene.js').write_text('unexpected partial write')
+ self.refusal()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_helper_boundaries.py b/tests/test_helper_boundaries.py
new file mode 100644
index 0000000..9aa5783
--- /dev/null
+++ b/tests/test_helper_boundaries.py
@@ -0,0 +1,82 @@
+"""MIT. New helper CLI boundaries, with fictional generated inputs and no user project."""
+import json
+import os
+from pathlib import Path
+import subprocess
+import sys
+import tempfile
+import unittest
+import wave
+
+KIT = Path(__file__).parents[1]
+HELPERS = KIT / 'Editing_OS/Tools/editing-workbench'
+
+
+class HelperBoundaryTests(unittest.TestCase):
+ def setUp(self):
+ self.temp = tempfile.TemporaryDirectory(prefix='helper-boundary-')
+ self.addCleanup(self.temp.cleanup)
+ self.root = Path(self.temp.name)
+ self.workspace = self.root / 'workspace'
+ self.workspace.mkdir()
+ self.config = self.root / 'config.json'
+ self.config.write_text(json.dumps({'schema': 'editing-pack-config/v1', 'workspace_root': str(self.workspace)}))
+ self.audio = self.workspace / 'silence.wav'
+ with wave.open(str(self.audio), 'wb') as w:
+ w.setnchannels(1); w.setsampwidth(2); w.setframerate(8000); w.writeframes(b'\0\0' * 800)
+ self.env = os.environ.copy()
+ for key in ['EDITING_PACK_ROOT', 'EDITING_PACK_WORKSPACE', 'EDITING_PACK_CONFIG']:
+ self.env.pop(key, None)
+ self.env['PYTHONDONTWRITEBYTECODE'] = '1'
+
+ def call(self, name, args, isolated=False):
+ return subprocess.run([sys.executable, '-B', *(['-S'] if isolated else []), str(HELPERS / name),
+ '--config', str(self.config), *map(str, args)], env=self.env, capture_output=True, text=True,
+ creationflags=getattr(subprocess, 'CREATE_NO_WINDOW', 0) if os.name == 'nt' else 0)
+
+ def test_audio_output_outside_workspace_is_rejected_before_write(self):
+ out = self.root / 'outside.json'
+ r = self.call('audio_motion.py', [self.audio, '--out', out])
+ self.assertEqual(r.returncode, 2)
+ self.assertIn('within the selected external workspace', r.stderr)
+ self.assertFalse(out.exists())
+
+ def test_audio_existing_output_and_source_are_immutable(self):
+ for out in [self.audio, self.workspace / 'exists.json']:
+ if not out.exists(): out.write_text('existing fixture')
+ before = out.read_bytes()
+ r = self.call('audio_motion.py', [self.audio, '--out', out])
+ self.assertEqual(r.returncode, 2)
+ self.assertEqual(out.read_bytes(), before)
+
+ def test_audio_rational_clock_cli_reports_bound_source(self):
+ out = self.workspace / 'measured.json'
+ r = self.call('audio_motion.py', [self.audio, '--out', out, '--fps', '30000/1001'])
+ self.assertEqual(r.returncode, 0, r.stderr)
+ data = json.loads(out.read_text())
+ self.assertEqual(data['fps'], '30000/1001')
+ self.assertEqual(data['frame_count'], 3)
+ self.assertEqual(len(data['source_sha256']), 64)
+
+ def test_missing_optional_pillow_has_explicit_profile_diagnostic(self):
+ out = self.workspace / 'unavailable.json'
+ r = self.call('style_inspect.py', [self.workspace / 'generated.png', '--out', out], isolated=True)
+ self.assertNotEqual(r.returncode, 0)
+ self.assertIn('Missing optional Pillow', r.stderr)
+ self.assertFalse(out.exists())
+
+ def test_demo_missing_draft_flag_and_unsafe_names_write_nothing(self):
+ for args in [['audio', '--job-name', 'plain'], ['audio', '--job-name', '../escape', '--allow-unapproved-draft-treatment']]:
+ r = self.call('capability_examples.py', args)
+ self.assertEqual(r.returncode, 2)
+ self.assertFalse((self.workspace / 'jobs').exists())
+
+ def test_studio_missing_resources_fails_required_profile_before_job_creation(self):
+ r = self.call('capability_examples.py', ['studio', '--job-name', 'missing', '--allow-unapproved-draft-treatment'])
+ self.assertEqual(r.returncode, 2)
+ self.assertIn('Missing three_module', r.stderr)
+ self.assertFalse((self.workspace / 'jobs').exists())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/toolkit.json b/toolkit.json
index 0bc25be..80991a2 100644
--- a/toolkit.json
+++ b/toolkit.json
@@ -2,7 +2,7 @@
"schema": "editing-pack-toolkit/v1",
"name": "Editing-Pack",
"layout_version": 1,
- "release_version": "0.1.0-rc.1",
+ "release_version": "0.2.0-rc.1",
"editing_os": "Editing_OS",
"contracts": "Editing_OS/Video Editing/Contracts",
"workbench": "Editing_OS/Tools/editing-workbench",