Repository navigation
Conversation
… 1 plan Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tution Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…and-written steps Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nition Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…AUDE.md mirror, manifest note Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…done Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…able, keep source paths Three findings from the whole-branch review. expand_for_each deep-copied every leaf of every step. It runs on every run of every workflow, after realize_args has turned 'asset:' and '*_image' arguments into loaded PIL images and decoded frame lists, so that multiplied the media a run holds - and a leaf that cannot be copied (an open handle, a live model object) failed a run that had always worked. A leaf is now copied only where the copy is needed: inside a member, where one template value is about to appear in every one of them, and there the copy falls back to the object itself when deepcopy raises, the choice the step cache already makes. The 'input untouched' contract holds because the pass never mutates a leaf. An unrelated undeclared 'variable:' made the pre-flight blame for_each: replace_variables raises on the first one, and the whole definition was then left unsubstituted, so a perfectly good 'shots' list reached the expansion as the literal string 'variable:shots' and the error said the list was never substituted - false, and it hid the actual typo. validation_errors now reports every undeclared reference at the path it sits at. That is an error rather than a warning because it is always fatal: once a workflow declares variables, replace_variables refuses an undeclared reference, so it is a run that cannot start. The check found one in workflows/templates/inpaint.json, which declared 'mage'. Reference errors on the expanded definition rendered expanded step indices - a path that exists in no file the author wrote. expand_for_each now records each expanded step's source index in a caller-supplied list (not a key on the step: step_data is what the step cache keys on and what the schema validates), and previous_result_reference_errors renders that index, naming the member in the message so the reader knows which expansion failed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…otes CLAUDE.md's older previous_result bullet still said a reference spelled by a 'variable:' is left alone, which the substitute-then-check order has made false in both directions: a declared variable's reference is checked by its value, and an undeclared one is itself an error now. The guide said two for_each steps over the same list are paired by name; the mechanism is by key - the entry's name, else its index - and it now states where an error's path points, since expansion no longer leaks expanded indices. The proposal records four observations for the stage-2 template rewrite: pipeline_reference naming a group gets no directed error, an entry field named image/*_image/*_video is realized before expansion, an empty list expands to no steps at all, and expanded_definition skips realize_constants. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n, schema, agent docs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…generation
T020 - run_workflow refused an argument *name* it did not recognise and
queued a bad 'asset:' reference anyway, so a typo came back as a job id and
a status: running, then died on the first step. The name half of the check
lives in JobManager.submit, where the definition is loaded; the reference
half needs the workspace's search path, so POST /api/jobs now makes the same
_argument_reference_errors call POST /api/validate does. Same message from
both, and nothing is queued.
T021 - a ModularPipeline (H3, LTX-2, Qwen-Image) has no
callback_on_step_end, so the route that reports every other pipeline's
denoise steps never fired: one 'generating' phase and then nothing for the
whole loop, which reads exactly like a hung run. Its denoise block drives a
tqdm bar instead, so reported_progress_bars patches that bar per instance
for the length of the call - every advance is a pipeline_step event and a
cancellation checkpoint, and the patch is undone on the way out. Uses
_blocks, not the public blocks, which hands back a deepcopy.
Beside it, a running job carries a `progress` block on GET /api/jobs/{id}
and on the MCP poll: the step, the phase and how long it has been in it,
seconds_since_event, and the denoise counter once that loop runs - kept as
events arrive rather than derived from a log that gets trimmed. That is what
separates a slow run from a stuck one between two otherwise identical polls.
T016 - proposal only, per Don: docs/proposals/output-folders.md.
Additive throughout; no field renamed or removed.
…oise progress + job progress block, T016 proposal
…ther variable Resolved once before realize_args, reported as undeclared at the entry's path, cycles refused. This is how a for_each template's optional voice variable reaches every shot the character speaks in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n error, fold lookup A variable cycle now surfaces as a validation error at path "variables" instead of escaping as a bare ValueError. resolve_variable_values reuses _resolve_variable_reference for the "variable:name" lookup instead of duplicating its not-found message. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ps over one shots list
Breaking for scripted callers: shot_1_wide_open .. shot_4_finale are
entries of 'shots' now, each {name, prompt, start_frame}.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ver a shots list
Breaking for scripted callers: shot_1_cold_open .. shot_5_tag, num_frames
and tag_num_frames are entries of 'shots' now, each {name, prompt,
references, num_frames}. An entry's voice reference names
character_a_voice / character_b_voice, so one variable still sets a voice
in every shot the character speaks in.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…me variables Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e before multiplying Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ing lead-in A modular pipeline spends up to ~90s inside `generating` before the denoise loop - encoding the prompt and any reference image or audio - and emits nothing. With `denoise_step` only appearing once there was a count, two polls a minute apart came back byte-identical with no counter, which is exactly the signature the docs call a hung job. `Job.progress()` now always carries `denoise_step`/`denoise_total_steps`, null until the loop starts, so the lead-in is distinguishable from a loop that has stopped advancing, and the MCP docstrings and docs state the rule that way: `seconds_since_event` only means something once `denoise_step` is a number, or in any phase other than `generating`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…der; test hygiene Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ntry strings validated; docs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…warning, rulings, flow-view edges Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n workflow's editor is not an orphan Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A phase says what a step is waiting on; nothing said what it cost. The events a job records carry no clock, so 'each H3 shot has a slow start' was an impression - the reference steps emit no loading phase (the pipeline is reused), and the gap between step_start and the first pipeline_step is the per-call encoding and CPU->GPU streaming, but there was no number to put on it. Job.add_event now stamps each event with `at`: seconds since the job started (since it was queued, for the events before that), beside `seq`. The SSE stream, the event-log page and MCP get_job_events pass it through unchanged; where a step's time went is a subtraction between two events. Documented in SERVER.md, MCP.md and the tool docstring. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
list_fields (dw/for_each.py) reads each step whose for_each names a variable and collects the item:<field> references its members read, so the catalog's listing and details carry a `lists` block - per variable, the fields an entry takes (name first), the steps that read it, and the default list's length. Compact listings carry it only when set, like `configures`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…he entry's path entry_field_warnings (dw/for_each.py) folds good arguments into a copy of the declared variables and, for each list-driven variable whose value is a list of dicts, reports every key of every entry that no step's item:<field> reads - a caller's typo (num_frame for num_frames) silently falls back to the template's default otherwise. Hooked into POST /api/validate's warnings alongside workflow_argument_warnings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…reaches inside list entries
per_entry on a cost entry names the list-driven variable it was measured
over, the minutes one entry costs, and the entries the default list held
- so a run over a different-length list can be priced from it rather than
guessed. Required, all three fields, additionalProperties: false. No
bundled template carries one yet (the numbers come from a later GPU run);
test_a_per_entry_cost_names_a_list_the_steps_read checks any that appear
against list_fields and the default list's length, and a synthetic case
in test_catalog_structure.py exercises the mismatch it exists to catch.
GET /api/workflows/{name}/variables' preview now recurses into list and
dict values, so a shot's prompt inside a list-driven default is cut to
200 characters like a top-level one, named in `truncated` as
`shots[0].prompt`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts; step cache holds a maximal run Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…of raising
expanded_definition realized constants over the whole variables dict, so a
'constant:' default that fails to resolve (unresolvable name, malformed
name, or one outside the trust allowlist) escaped validation_errors as an
unhandled exception rather than the usual [{path, message}] shape. Realize
per top-level variable instead, wrap the three exceptions fetch_constant
and realize_constants can raise in a new ConstantError(path, message), and
catch it in validation_errors beside ForEachError - so POST /api/validate
reports 'variables.<name>' with the real message instead of swallowing it
into a generic 500. Workflow.run is unchanged.
Also: moved the empty-list check in for_each.py's _entry_keys ahead of the
ceiling check, and dropped the tombstone comment left where the deleted
empty-group gather test used to be.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…by the skill and the guide Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…trings match lists/per_entry
dw/validate.py never called set_trust_workflows and had no --trust-workflows
flag, so validating a workflow whose variable default realizes an
out-of-ecosystem 'constant:' name failed with a message telling the user to
pass a flag the command lacked. Mirror dw/run.py: add the same argument and
call, same help text. Pins the UntrustedWorkflowError -> ConstantError branch
in dw/workflow.py with a test that validation_errors() reports it as
[{"path": "variables.<name>", ...}] rather than raising, and that the same
definition validates once trusted; also pins that dw-validate's
--trust-workflows actually flips the gate before the workflow loads.
dw_mcp/server.py's list_workflows/get_workflow tool docstrings and the
server-level instructions still described the pre-list-driven catalog shape
(no `lists`, wrong wording for per_entry and the 200-char preview into list
defaults) - bring them in line with what dw_mcp/catalog.py and docs/MCP.md
already say.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rnings surface docs/SERVER.md's full GET /api/workflows listing paragraph named neither `lists` nor per_entry cost, though the compact-view bullet right below it already did; "plus the four new fields" was also stale since lists and per_entry pushed the count past four. Its POST /api/validate paragraph did not mention that `warnings` also covers an unread entry key of a list-driven variable. docs/MCP.md's validate_workflow row didn't mention warnings at all. docs/WORKFLOW_GUIDE.md's for_each Limits paragraph didn't yet say an empty list is a validation error or that validation realizes a constant: default before checking it - CLAUDE.md's Type System bullet already states both. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…batim The brief asked for the same help text as dw/run.py's flag; the first pass paraphrased it instead of copying it, which would have let the two commands' --help drift apart again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.