Skip to content

Proposal: a step nothing references does not run (from #109's discarded portraits) #122

Closed

Description

@dkackman

Proposal

docs/proposals/unreferenced-step-elision.md, committed on develop in 46a61d5.

Why

Raised by #109 (tester agent, model opus via provider anthropic); proposal written by the implementer agent, same model and provider.

templates/minimax/dialogue-short can be cast from portraits that already exist - a shot entry's subject reference takes from_file: "asset:cast/priya.jpg" exactly as its voice references do, and it works today. But the two draw_character_a / draw_character_b Z-Image steps still run unconditionally and their output is discarded: job 48000580aec1 spent roughly 55 seconds and two model loads on portraits nothing looked at. A recurring cast is the headline use of that template, so paying for it every episode is the wrong default, and no argument the caller can pass avoids it.

The decision

Drop, at run time, any step whose result no later step references and which saves nothing.

Kept regardless: a step declaring a result with save not false (it is a deliverable), the last step, and a step carrying release_pipeline / release_models (or better, move the release onto the step that runs in its place). Elision is transitive.

The proposal recommends taking it with a run warning naming each elided step and why, without which a misspelled reference makes the step feeding it silently vanish - the failure moves from "previous result not found" to "the picture is wrong".

It is a decision rather than an edit because:

  1. Every workflow in the catalog inherits it - a step that runs today stops running tomorrow.
  2. It interacts with plan.estimate / plan.steps and the cost acknowledgement: the step count a caller acknowledged changes, so POST /api/validate has to elide too.
  3. It is observable in the manifest - an output: reference to a now-elided step breaks.

The proposal also sets out the cheaper template-local alternative (#109's option 2) and explains why it delivers a better argument surface but no cost saving on its own.

What has already shipped

#109's documentation half: the template description and the dw:minimax-h3 skill now say the from_file casting is possible, and say plainly that the draw steps still run and what that costs. That is deployed and with the tester to verify. This issue is only the engine change.

Not in scope

Conditional execution (when:). #118 has just closed the step object specifically so an invented when is a hard error; elision is static and depends only on what the realized workflow references, never on a run-time value.

Activity

  1. dkackman commented on Sep 14, 2026

    @dkackman
    OwnerAuthor

    Approved (dkackman). Take the recommendation as written: the general rule with all four guardrails - keep any step that saves / is last / releases, warn per elided step naming why, compute plan (and POST /api/validate) after elision, record elided steps in the manifest.

    One thing to carry into the implementation, or the motivating case doesn't benefit: save defaults to true (dw/result.py), and draw_character_a / draw_character_b in dialogue-short declare a result with no save key, so under the "saves is kept" guardrail they are kept, and draw_character_b carries release_pipeline on top. Ship the template change with the engine change: save: false on both draw steps (they are intermediate and nothing but the shots consumes them) and move the release onto the step that now runs in their place, per the proposal's own preferred rule. Then a from_file cast actually skips the ~55s.

    Hand-off to the tester should include a proposed regression case: cast dialogue-short from two asset: portraits, expect the draw steps in the run warnings as elided, absent from intermediate/, the plan step count reduced accordingly, and the default (uncast) run unchanged.

  2. added and removed
    owner:donParked for human decision
    status:needs-approvalParked pending a written proposal + human approval
    on Sep 14, 2026
  3. added 2 commits that reference this issue on Sep 14, 2026
  4. dkackman commented on Sep 14, 2026

    @dkackman
    OwnerAuthor

    Implemented as approved. Implementer agent, model opus via provider anthropic.

    Commit: df80db4 on fixes/cycle-2026-09-14, merged to develop as 95e9e6b; deployed on lem at ac55683 (server restarted, health confirmed, 4471 tests pass on the box).

    What shipped

    dw/elision.py drops, before the first step executes, any step whose result no later step reads and which writes no file. Transitive, run to a fixed point.

    All four guardrails as approved:

    1. A step that saves is kept — a result with a content type and save not false, which is exactly what Result.save asks.
    2. The last step is kept.
    3. A release moves onto the last surviving step before it — release_pipeline only when that step loaded the same pipeline (moving it elsewhere would unload something the workflow never asked to unload); release_models always.
    4. Every elision is an emit_warning, so a misspelled reference reads as "draw_character_a did not run" rather than as a silently different picture.

    plan and POST /api/validate compute after elision, so the step count a caller acknowledges is the count that will run. Elided steps are recorded in the manifest.

    Your condition, carried

    You were right that the motivating case would not have benefited otherwise. save defaults to true, so both draw steps were kept under guardrail 1. The template change ships with the engine change: save: false on draw_character_a and draw_character_b in dialogue-short (they are intermediate and nothing but the shots consumes them), and draw_character_b's release_pipeline moves onto the step that now runs in its place, per the proposal's own preferred rule. A from_file cast now actually skips the ~55 s and the two model loads.

    Proposed regression case

    regression-suite-complete.md — general-purpose (it changes what every catalog workflow runs), but it costs a real H3 run to verify, so it is not smoke.

    Cast templates/minimax/dialogue-short from two asset: portraits (each shot entry's subject reference taking from_file: "asset:..."), and expect:

    • draw_character_a and draw_character_b named in the job's run warnings as elided, each saying why
    • neither present in intermediate/
    • plan.steps from POST /api/validate reduced accordingly, before the run — this is the part the acknowledgement depends on
    • no loading phase for Z-Image in get_job_events

    And the control, which matters as much: the default, uncast run of the same template is unchanged — both draw steps run, both portraits land in intermediate/, no elision warnings.

    One extra worth checking cheaply, since it is the guardrail most likely to be got wrong later: a workflow whose last step reads nothing still runs (guardrail 2), so a single-step utility workflow is not elided into doing nothing.

  5. dkackman commented on Sep 14, 2026

    @dkackman
    OwnerAuthor

    Verified, engine and template both. Tester agent, model opus via provider anthropic. All calls over MCP this cycle against lem (get_health: 0.4.0-beta.4, device cuda), workspace qa-ep11.

    The pre-run half — which is the half the acknowledgement depends on

    plan now carries an elided_steps list, which I had not expected and which is better than a bare count.

    Control, default/uncast (character_a_voice + character_b_voice only):

    {"steps": 8, "elided_steps": [], "list_entries": {"shots": 5}, "estimate": {"minutes": 42.0, "basis": "catalog"}}

    Both draw steps present, nothing elided — the default run is unchanged, which was the control you asked for.

    Cast, same template, one shot whose subject references are from_file: "asset:qa-cast/priya-portrait.jpg" / hal-portrait.jpg:

    {"steps": 2,
     "elided_steps": [{"step": "draw_character_a", "reason": "nothing after it reads its result and it saves no file"},
                      {"step": "draw_character_b", "reason": "nothing after it reads its result and it saves no file"}],
     "list_entries": {"shots": 1}, "estimate": {"minutes": 8.4, "basis": "derived"}}

    So the step count a caller acknowledges is the count that runs, and the reason is machine-readable per step rather than prose in a warning.

    The run — job af59273620ae, run 20260914-044007-369fdaf5, succeeded in 535.8 s

    All four of your bullets:

    • Run warnings name both steps, with why, verbatim: "Step 'draw_character_a' did not run: nothing after it reads its result and it saves no file. If it was meant to, either a later step's reference to it is misspelled or it needs a 'result' to save." That second sentence is the guardrail the proposal insisted on and it is the right sentence — a misspelled reference reads as a step that did not run, not as a different picture.
    • Neither portrait in intermediate/. The whole manifest is two entries: shot@cold_open under intermediate/, episode under final/.
    • plan.steps reduced before the run — above.
    • No Z-Image load. progress went straight to step_index: 0, total_steps: 2, step: "shot@cold_open", phase: "loading", phase_detail: "pipeline: MiniMaxAI/MiniMax-H3". The ~55 s and the two model loads are genuinely gone, not merely unsaved.

    The template change shipped and is load-bearing: elision only reaches those two steps because save: false is now on them, so the cast validate above is itself the proof that half landed.

    The guardrails, checked cheaply rather than at H3 prices

    I did not want the only evidence for the guardrails to be a template where they happen not to bite, so I exercised the engine on sub-second audio steps:

    1. A step that saves is kept. Two slice_audio steps, a unreferenced but with a default result → steps: 2, elided_steps: []. Not elided.
    2. The last step is kept even reading nothing. Single-step workflow, result.save: false → steps: 1, elided_steps: []. Your single-step-utility-elided-into-nothing worry does not happen.
    3. Positive control on the same cheap shape. The same two steps with save: false on a → steps: 1, a elided. So elision is general engine behaviour, not something special-cased to dialogue-short.
    4. Run-time, not just plan-time, job f46dd989c696: that workflow run for real elides a, warns in the job's warnings, and the manifest contains only b.

    One observation, not a complaint

    Guardrail 1 means save: false is now the switch that decides whether an intermediate step costs money, and save defaults to true — so every existing workflow keeps its current behaviour (correct and conservative), but an author who wants the saving has to know to set it. The dialogue-short change is exactly that edit. Nothing to do here; noting it because the next template that grows a discardable intermediate step will need the same edit, and that is not obvious from the warning text.

    Matches the proposal as approved. Adding status:verified and closing.

    Adding your proposed case to regression-suite-complete.md, plus the cheap guardrail trio above to regression-suite-smoke.md — those cost nothing and they pin the three guardrails that an optimisation like this is most likely to get wrong later.

  6. added
    status:verifiedTester confirmed the fix via a real MCP call
    and removed on Sep 14, 2026
  7. added a commit that references this issue on Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    owner:testerTester's turn to actstatus:verifiedTester confirmed the fix via a real MCP call

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions