Skip to content

Develop - #86

Merged
dkackman merged 63 commits into
masterfrom
develop
Sep 12, 2026
Merged

dkackman merged 63 commits into
masterfrom
develop

Conversation

@dkackman

Copy link
Copy Markdown
Owner

No description provided.

dkackman and others added 30 commits September 12, 2026 09:32
…ery surface)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…t, segment pattern, step_output_dir, step_end, sub-workflows, steering rule)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…aps it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e_name after expansion

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… name not a path

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… feeds Result.save and the pipeline wrapper

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every manifest step entry and step_end event now carries "subfolder"
(empty string when the step is unfoldered, the definition's subfolder
on a cache hit). Adjusted the exact-key-set assertion in
tests/test_workflow_step_cache.py::test_cache_hit_marks_its_manifest_entry_and_event_reused
to include the new field.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…id wins; CLAUDE.md states the output: ceiling

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Replaces mcp-feedback.md in the iterate harness repo: tickets now live as
GitHub Issues on this repo, with owner:*/status:* labels standing in for
the old owner/status fields and comments standing in for notes/verify-notes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… CLAUDE.md dedupe, fence, wording)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… subfolders list

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…orkflow state the subfolder convention

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…termediate convention in the authoring guide and its CLAUDE.md mirror

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n spill lands in the step's subfolder

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ads straight

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…te is convention

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Design for a since_seq/last_seq cursor on wait_for_job/get_job_events
(mirroring the SSE endpoint's existing resume semantics) plus an explicit
failure_kind field, to close the gap where an active polling loop can
silently miss a job's terminal transition (completion or OOM-kill).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ts bullet, CLAUDE.md period

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every saving step of a template with two or more saving steps carries
result.subfolder - final for the output the user is shown, intermediate
for the scratch that went into it. tests/test_template_subfolders.py
asserts the rule so it cannot drift and pins the packaged builtins as
unmarked: a role is the parent's to assign.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Where the skill reads the manifest it now says what the family's templates
put in final and intermediate, that list_gallery(subfolder=) filters on it,
and that a composed workflow keeps the convention. Pinned against the
templates' actual roles.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ms in CLAUDE.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… is the builtins', not their parents'

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dkackman and others added 29 commits September 12, 2026 13:34
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…first

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…headings

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…stages done

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ds live from step_end; doc and test tidy-ups

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The newest-N slice started at `len(jobs) - limit`, which goes negative once
the limit exceeds what matched and is then read from the end: `limit=12`
against 9 matching jobs answered with the last 3 and reported 6 "not listed".
Only bites when `len < limit < 2 * len`, which is why the same data at
`limit=20` looked correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The result is already in host memory and saving never touches the pipeline,
so the old ordering held ~10 GB on the device through the longest phase of a
video step. Releasing now also clears the loop's own reference to the step
action and reclaims on the spot - a popped pipeline the frame still holds is
not freed. A sub-workflow's manifest is read before the release so the
rollup is unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…uilt

Two leaks that compounded across retries:

- Pipeline.load kept whatever it had built when it raised partway - the
  pipeline, its quantized weights, a half-applied placement - and the caller
  never received it, so nothing dropped it. It is now torn down and
  reclaimed on the way out, and a component shared before the failure is
  unpublished so no later step reuses a component of a pipeline that does
  not exist.
- The worker reclaimed on success and on cancellation but not on failure:
  no collection, no device-cache empty, and no eviction of the variants the
  attempt superseded. It now does all three. The exception's traceback is
  dropped first - it reaches every frame between the handler and the
  failure, so a collection with it still live frees none of what those
  frames hold.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
They are the engine's answer to decode memory pressure and carried no
description, so the schema did not say that decoding a batch one sample at a
time is already available.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ng, memory

- ltx-2.5: the write-out warning states ~4 s/frame at 1536x896 so a reader
  can scale it to any frame count, rather than "minutes" at 121 frames (#76);
  intermediate steps take `"result": {"save": false}` (#77).
- minimax-music3: the generated arc stretches to fill audio_duration, so the
  ceiling is set at 1.5x the intended length and trimmed (#78).
- both: check idle gpu_memory_allocated_mb with get_memory before a
  near-ceiling render, and ask for a worker restart rather than retrying into
  what a failed attempt left behind (#79).

Trimmed prose elsewhere in the ltx skill to stay under the 12 KiB cap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
/api/memory answered live/info only, so a cached reading taken while a job
was loading a model was indistinguishable from a live idle one - and reads
low, which is wrong in the dangerous direction. The response now carries
stale, reason (job_running, worker_stopped, worker_busy, worker_unreachable)
and age_seconds beside the existing keys, and info: null keeps its meaning:
nothing has been measured because nothing is resident.

The get_memory tool description, docs/MCP.md and docs/SERVER.md state what
live means and that only live readings compare with each other; the ltx-2.5
and minimax-music3 skills' memory step gives the rule for each state.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The tool description promised "VRAM and RAM" and returned only the card.
On this box that is the less informative half: the templates offload
weights to host memory by design, so a generation can run with ~8 MB
allocated on the GPU while the weights are very much resident - which is
exactly the leak path #72 describes and the one a consumer could not see.

host_memory_stats() reads the worker process's RSS and high-water mark
and the machine's total/available, via psutil when it is installed (a
transitive dependency here, never required), /proc otherwise, and
resource(2) for the peak. Nothing raises; a reading the platform cannot
take is left out of the payload rather than sent as null, so an absent
key means "not measurable here" rather than "measured, and nothing".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The release moved to before the write in 2e2ac05, and the tester found
the ordering unverifiable from outside: it happens inside the window
between a step's generation and its files appearing, which is 0.4 s for
an image step, and nothing in the event stream marked it. Polling
get_memory cannot land a sample in that window.

A step with release_pipeline now emits `pipeline_released` (step, index,
allocated MB before and after, null where the backend cannot say), which
sits before that step's `step_end` - so the ordering reads directly off
get_job_events on any workflow, at no GPU cost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Shots generated independently land at whatever level the model chose -
two shots of one scene measured -2.65 and -12.56 dBFS peak - and each
reads as fine alone, because a shot is only wrong relative to what it is
cut against. Butt-joined that is an audible drop, and it is the one seam
artifact none of the fade controls can touch: it is either side of the
seam rather than at it. The workaround was normalize_audio + pair_audio
per shot, two extra steps each, ten for a five-shot cut.

`match_levels` ("rms" for perceived level - the measurement
get_gallery_metadata reports as mean_dbfs - or "peak") scales every track
before the join, to `match_levels_dbfs` or the measure's default; a gain
that would clip is held just below full scale and logged. Off by default,
so nothing existing changes, and an unmatched join whose tracks span 6 dB
or more says so in the log rather than passing in silence.

Both cut templates and assemble-and-score expose it as a variable,
defaulting to null, so a run can even its shots out with an argument.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The metadata route decodes an audio or video file whole to probe it, and
the job page showed nothing a probe supplies - so a multi-shot video job
opened with one full decode per clip. Under the flat output layout two
runs share file names, so the map now clears on a job change. Both seed
draws use OS entropy; model ids read in mono, as the engine reads them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The page reads each image's embedded metadata and links a download, so
the mock has to answer both; one test pins that a video is never probed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@dkackman
dkackman merged commit 2ecaa22 into master Sep 12, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant