Preserve forwarded Result values without eager materialization, advance live Builds from disposable indexes, and bound HyperFrames resource, source-frame, and output work.
* fix(generation): refuse supplied media fields a provider cannot carry
* fix(media): probe selected tools in their execution environment
* fix(credentials): use native file replacement across processes
* fix(runtime): distinguish tool preparation from process startup
* fix(cli): bootstrap from the physical distribution directory
path.relative of a workspace file named ..keep.svml is the string
..keep.svml. Treating any relative result that starts with .. as an
escape rejected that file as SOURCE_OUTSIDE_ROOT, and the same
predicate was copied into source discovery, Build Result project
paths, Studio writes and CLI short paths.
Use the repository's existing check: only `..` and `..${sep}` are
parent traversal. A Source still cannot import ../outside.svs.
Reserve the trailing UTF-16 NUL required by the Win32 rename API while keeping FileNameLength exclusive of the terminator. Verify exact destination names and open-reader behavior, and close test runtimes on failure before removing their SQLite files.
Keep reused media as explicit references, publish Result changes only when needed, and replace Windows files without timed retries. Clarify environment selection and CLI output.
Refine Studio task and media browsing, editable display names, inline media previews, single-row track overlap, semantic ruler pinning, and Companion-owned Ranking selection.
A Windows stress run failed three times in ten, each the same shape: one Build
complete and the other with no Result written at all. A Build with no Result has
not failed, it has stopped being scheduled, and the message said nothing about
why. Dump the execution snapshots and Operations at the deadline: `wakeAt`
absent means waiting on a resource release, which separates a lost wake-up from
ordinary waiting.
The Result manifest carries `failure` beside `outcome`, and the wait read only
the outcome. A Build that reached `failed` therefore reported the state and not
the reason, which is the one thing the Windows runs needed to say.
Under load the test failed `1 !== 2` on "a later Build must join work already in
progress": the first handler held for a fixed 80 ms and the assertion required
the Worker to admit the second Build, plan its graph and reach the same producer
inside that span. Forty runs against a loaded machine reproduced it eight times.
The first handler now holds until the second one actually starts, bounded at
10 s, so the overlap no longer depends on machine speed. A Worker that serialized
the Builds waits out that bound and the assertion reports it. The same forty runs
now pass forty times.
The poll for terminal outcomes also stops on any outcome other than `complete`
and names it. Only `complete` ended that wait, so a Build reaching `failed` was
waited on until the deadline and then reported as a stall, which is how the
Windows failure read.
Closing the SQLite state in `finally` while `runtime.work` was still running
turned the Worker's next `claim` into an unhandled rejection, which node reports
in place of the assertion that failed the test. The abort and the wait for the
loop now happen first, bounded so a loop that will not stop cannot hold up the
cleanup, and the removal retries rather than failing on a handle Windows has not
released yet.
The run this came from is the answer the earlier masking hid: the test failed at
30.5 s, so the deadline fired and the two Builds did not reach a terminal
outcome. That stall is the same one that hung the job for 97 minutes and is
still unexplained.
A Windows run failed two tests whose messages named neither cause.
"one local Worker admits later Builds" reported `EBUSY ... unlink
runtime.sqlite`. That is the cleanup: a throw above skips `runtime.close()`,
SQLite keeps the file open, and the removal in `finally` fails on Windows and
replaces the error that failed the test. Closing the state in `finally` lets
that error through.
"one live detached Runtime Worker" reported `another Runtime Worker launch did
not finish in time`, which is the sibling call giving up on the launch lock
rather than the launch it was waiting for. Carrying the Worker log into the
failure gives the next one something to read.
Re-running the same commit passed, so both remain intermittent. This changes
what they print, not how often they fail.
A Windows job on f80a562 sat for 97 minutes after its last output. The suite had
reached "one local Worker admits later Builds while preserving shared Endpoint
capacity", whose poll for two terminal Build outcomes carried no deadline; one
Build did not complete on that run, so the loop polled every 5 ms until the job
was cancelled. Re-running the same commit passed, so the stall is intermittent
and its cause in the Worker launch path is not yet identified.
Three bounds now apply. The poll fails after 30 s and prints each Build's last
outcome. `node --test` receives `--test-timeout=120000`, well above the 5.75 s
slowest test measured on that run. The job takes `timeout-minutes: 20`.
`-Command -` parses stdin a statement at a time, so an argument holding a
newline ended the statement early: PowerShell exited having run nothing, with
no process id and nothing on stderr. Any launch whose arguments carry a real
newline hit it — `node -e` with an actual script is the ordinary shape, and it
is what `ensureRuntimeProcess` is handed in its own test.
Send the script as one `-EncodedCommand` blob instead. It keeps the property
that made stdin attractive — no quoting of ours crosses a shell boundary — and
base64 has no line structure to end a statement early.
Regression from 3063fa6, which routed the Worker through this helper; Managed
Programs were only ever given single-line arguments and so never showed it.
Windows ties a process's lifetime to the console it is attached to, and the
Worker inherited the launching CLI's. When that command exited its console was
destroyed and the Worker went with it, so a submitted Build sat at `0/n steps`
with an empty Worker log and nothing to read anywhere.
`programs.ts` already solved this for Managed Programs: `detached` on Windows
means DETACHED_PROCESS and no console at all, while `Start-Process
-WindowStyle Hidden` creates a hidden console of its own. Export that helper
and use it for the Worker too. POSIX keeps `detached`, which is what grants it
its own session there.
Group requests by endpoint and rate material, summarize explicit no-charge work, and preserve every priced request in JSON. Providers may supply a concise summary alongside their original rate documents; the CLI does not infer prices or walk upstream media dependencies.
Let HyperFrames render explicit frame intervals with independent browser workers, and make Runtime account for request-dependent resource units across Builds. Preserve external Operations while stopped executions settle so capacity is released only after real work ends.
Studio can only show media that has been normalized, and normalization is a
Need served by the Profile's local FFmpeg Endpoint. A Studio that installs no
Endpoint therefore rejects every file Candidate: satisfying the generated
output leaves inspect-media and normalize-media unresolved, and a file cannot
satisfy the normalized output's type. The deleted path-based preview bypass
answered this question with the wrong mechanism; this is the right one.
The Runtime Host gains localEndpoints(): every Endpoint the Profile selects
whose Provider declares local pricing, immediate capabilities only, with the
Profile's bindings applied. A capability bound to a priced Endpoint stays
unresolved rather than falling to a local one. Studio preflight and execution
resolve Needs through that registry, exactly as plan and a Build do minus every
priced Endpoint, and name the capability when a Need reaches nothing free.
Verified on the media-track preview with three file Candidates and an
estimated semantic take: normalized through media.local and displayed in
306 ms. Duplicate studio.svrun files that were byte-identical to a sibling Run
are removed; a Run's path carries no semantics.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>