Resolve the argument and require a regular file before spawnSync, which
never uses a shell and only runs fixed binaries or that validated path.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Shadow maps use the full scene-derived size (point-light faces capped
at 2048) under a 26M-texel scene budget halved largest-first; the PCF
filter measures its reach in output pixels with a two-texel minimum,
samples texel centres on a jittered adaptive 5..10 grid, and compares
each texel against the receiver plane's own depth so wide kernels never
self-shadow lit casters. The WGSL mirror is parenthesised (Tint rejects
the old form) and guarded by a shader-wide grammar test; the CPU
reference and shader remain step-for-step parity-tested.
Reload Footage probed every item the way File ▸ Import does by default,
so a still such as Photo_2.jpg with Photo_1.jpg beside it was grouped
into a run and measured from the run's first file. The still took
Photo_1's size. Sequence items still probe as a run; everything else
reads its one file.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A raster footage layer's Timeline menu now also has to leave out Create Shapes from Vector Layer. The viewer check keeps the solid selected, so the menu has to follow the layer under the pointer rather than the selection. With the viewer's caps merge made a no-op, the test fails at the viewer check.
file.projectSettings takes frameStart (0|1), the Project Settings dialog shows Frame Count, and scripts get app.project.framesCountType and displayStartFrame. The setting was already read by the Frames and Feet + Frames time display; nothing could change it.
Double-clicking a property name in Effect Controls did nothing. The test double-clicks the name and checks the Timeline marks the property revealed and shows its row. Without the fix nothing is revealed.
The focused panel's outline was painted before the panel body, so body fills hid it. The test finds the outline in the painted shapes and checks no filled rect painted after it reaches its one-pixel ring. Without the fix a body fill overlaps the ring.
Right-clicking vector footage in the Timeline or the Composition viewer offered no vector conversion. The test imports an SVG and checks the item is absent for a solid, present on the SVG layer in both menus, and converts it. Without the fix the menu item is missing.
Resampling footage audio divided by the requested mix rate, so a rate of 0 panicked. The test decodes a 44.1 kHz WAV at rate 0 and expects a read of the requested length. Without the guard it panics with 'attempt to divide by zero'.
Nothing cleared a `Value::Layer` reference when its layer was deleted, so the id stayed behind:
`env_pixels` resolved it to nothing and rendered no environment at all, while the UI showed "None",
which is documented as "fall back to the comp's Environment Layer". The delete path already
unparents children and drops a track matte that pointed at a deleted layer; a layer reference now
goes the same way, in the same history step, so undo restores the layer and the reference together.
This covers every layer-reference property, not only an Environment light's Source: 73 of them
across the effects (Clone Source, Set Matte, Back Layer, Water Surface, Sky, Ground…). Keyframes
carry the same value kind as the property, as in `essential.rs`, and are fixed too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The setters go through `comp.settings`, which defaults to the Composition Settings dialog's
centre anchor, so `comp.width = 800` on a 400-wide comp shifted every unparented layer — and
all of its position keys — by 200 px. A script that resized a precomp then found its pixel
coordinates had moved under it.
After Effects' width and height setters only change the frame; moving the contents is what
"resize from centre" scripts do for themselves. The setters now pass `anchor: 0` (top left).
The dialog, which is where the anchor belongs, is untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Composition Settings dialog draws 「ピクセル縦横比」 and 「フレーム縦横比」, and its checkbox reads
「縦横比を 1:1 (1.00) に固定」. Three existing rows said アスペクト比.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
The menu is the authority and it disagreed with this table in three ways: five rows had been
translated that AE leaves in English (Key Cleaner, Advanced Spill Suppressor, Unmult,
Twirl (Legacy) and mocha shape), eight use a half-width ampersand, and a handful differ only in
spacing (Cineon コンバーター, 3D カメラトラッカー, 基本3D). Five effects the table skipped do have
names: コンプレッサー, 歪み, ゲート, カールノイズ and VR 平面として投影.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Adobe help calls it エクスプレッション制御 in prose; the Effect menu says 式制御. The menu is what
a user reads, so it wins.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Read from the Effect menu: OCIO CDL 変換, OCIO 色空間変換, OCIO 表示変換, OCIO ファイル変換 and
OCIO Look トランスフォーム. AE draws 稲妻(高度) and 輝度&コントラスト with half-width marks while
平均化(イコライズ) keeps full-width ones, so the punctuation follows the menu per effect.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
An array replacer now copies each source object once per call, so a cycle stays a cycle and the native check throws TypeError, while shared objects still serialize. Documents which threads evaluate expressions, what the 256 KiB guard covers (tested on a 512 KiB thread), that it does not apply on wasm32, and why eval is indirect.
Key Cleaner is キークリーナー and Advanced Spill Suppressor is 高度なスピルサプレッション —
neither is a brand name, and Adobe's keying page names both. The doc comment claimed the
VR and OCIO sets repeat their English names here; the VR rows are Japanese now and the OCIO
rows do not exist, so it says what is true instead.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
285 of 307 ids. The 22 that stay English are the ones no source names: the OCIO set,
Screen Key, Unmult, Curl Noise, Puppet, Twirl (Legacy), Stereo 3D Controls, the two face
tracking effects, Mocha shape, Paint, and three audio effects.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Adobe's per-effect pages say 色合い / レベル / 露出 / ストローク / ストロボライト, but its effect
list says 色かぶり補正 / レベル補正 / 露光量 / 線 / ストロボ, and the list is what AE's
interface follows. The interface wins.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
The Timeline drew a layer-valued property (an Environment light's Source, a
Displacement Map's layer parameter) as read-only text holding the raw layer
id, so a light's Source could not be chosen in the UI at all - only through
prop.set from the command line, scripting or MCP. Effect Controls already
had a working drop-down for exactly these values: extract it into one shared
widgets::layer_picker (the current entry, "None" first, then "N. name" for
every layer of the comp, the list built only while the popup is open) and
draw it from both panels.
In the Timeline the pick writes through the same set closure as every other
value arm - an undoable prop.set (layer id, or null for None) - and
registers timeline.prop.<uid>.value like its neighbours, so the row names
the layer instead of exposing its id. Effect Controls keeps its rect,
automation id and write; its closed dropdown's "None", previously a
hardcoded literal, now follows the interface language. The dead "Layer {n}"
id text leaves the i18n catalogs with it.
ui_layer_source_picker drives both panels headlessly (open, pick, undo,
dismiss, current-entry highlight, translated None, picking None to clear a
set value), and an ignored wgpu snapshot test keeps the visual record
reproducible.
Tint is 色合い, Levels is レベル, Exposure is 露出, Stroke is ストローク and Strobe Light is
ストロボライト. The list used for cross-checking carried Photoshop's words for three of them.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Every selector of a comma list cloned the whole declaration block, and every
element scanned every rule, so a sub-megabyte <style> could demand billions of
string pairs. Selectors now index one shared block, the sheets are capped at
20 000 selectors and 50 000 declarations, rules are bucketed by id/class/type
so an element checks only candidates, and matching work over all elements is
charged against a 50M-step budget that fails the import instead of doing it.
eval, Function and the generator/async function constructors now check the nesting of their source like the expression text. join, toLocaleString, flat and JSON.stringify check the run's stack use per level, results nested past the detached levels become [object], and Proxy/Reflect are no longer available to expressions. Each of these overflowed the stack and aborted the app.
148 of the 307 ids. Names from AE 2026's Japanese interface and from Adobe's Japanese help,
which is what settles the `CC` rows staying English and `Smart Blur` being `ブラー(詳細)`.
Three rows rest on elimination and are called out in the PR.
Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
Found while testing crates/geom/src/lib.rs:362-390 (pivot check at line 367)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The per-accessor count checks from #1235 already reject the audit's trigger
(a MAT4 accessor with count 10^11); a regression test now pins it. What was
left: accessors without a bufferView were capped at 16M components each, but
nothing backs them, so one capped accessor referenced from many primitives
allocated 64 MB per reference. The cap is now one budget for the whole file.
Per-element offsets use checked arithmetic as well.
The test checked that Japanese text falls back to an installed Japanese
family, but left the process-global CJK locale at the host's: on a zh-CN
host with a Chinese face installed, han_order puts the Chinese families
first for the shared ideographs and the Japanese-family assertion fails.
Set ja-JP under the TEST_CJK_LOCALE lock and clear the request when the
test ends, as the zh-CN test beside it does.
Tests: effectcraft-text 75 lib + 3 integration passed; cargo fmt --all -- --check passed.
1,626 is the Traditional Chinese total translated-string count; the panel
catalogs carry 998 source rows each (996 in Japanese), as
docs/localization-parity.md measures.
Review follow-up to the panel/dialog step: the composition-settings tabs
translate "Basic" and "Advanced" through `tr(variable)` and the Preview
transport translates "Play/Stop", but none of the three had a catalog
row, so they stayed English. Add them to the Japanese, Simplified and
Traditional Chinese catalogs and pin them in
`japanese_rows_translate_the_panels`.
The shared "Type" key means "kind" in the Project column and the Camera
Settings dialog, so the Chinese rows read 类型/類型 instead of 文字
("text").
Keep the graph button bar's automation labels English: translate only
the drawn label and tooltip, and translate the stored English strings
when the hidden-button menu draws them.
Recount the docs from the catalogs: 628 menu rows, 996 Japanese and 998
Chinese panel rows; count Simplified Chinese's 306 effect names in its
numerator (46%) and average the ten After Effects languages the table
actually names (21%, not the stale 27%). Update the measurement basis,
the cross-references in gaps.md and target-app-parity.md, and ROADMAP.