Skip to content

validate_workflow: composing a template through a workflow step loses its measured cost basis #268

Closed

Description

@dkackman

Both hysteresis and hysteresis-ltx2.5 (workflows that compose other templates as steps) answer basis: "unknown", partial: true from validate_workflow — even though the templates they compose each carry their own observed_minutes (6.6 min over 2 runs for one; 2.76 min over 11 runs for the other).

Naming/wrapping a template as a step in a composing workflow makes the whole thing permanently unpriced, regardless of how well-measured the piece is on its own.

Ask: a composing step should be able to inherit the composed workflow's basis (and roll its observed timing into the composing workflow's own estimate), rather than the composition itself resetting to unknown every time.

Related: #255, #267 — the same plan.estimate surface not reflecting what's actually knowable about the plan.

Activity

  1. dkackman commented on Sep 21, 2026

    @dkackman
    OwnerAuthor

    triage: batch with #255, #267 — same dw/plan.py estimate code; #255's session does the work. The docstring on estimate says a composed child is deliberately not added when the parent has an observed run; the gap is when the parent has no figure and the child does — that is the case to fill. (triage by implementer agent, model opus via provider anthropic; lem is at develop head c5d4ac5, so nothing here is fixed-but-undeployed)

  2. added a commit that references this issue on Sep 21, 2026
  3. dkackman commented on Sep 21, 2026

    @dkackman
    OwnerAuthor

    Fixed. A composing parent workflow (no cost of its own, every declared step a workflow step assembling children) now rolls up a fully-observed child's history into the parent's estimate with basis: "observed", instead of reporting basis: "unknown", partial: true.

    Two parts in dw/plan.py/dw/server/app.py:

    Shipped as part of a batch with #255 and #267 (all three are fixes to dw/plan.py's pricing logic), one branch, one deploy.

    Suggested regression case (for the tester to add once verified): in regression-suite-complete.md (composes-workflows trait, edge-case-y), validate a parent workflow whose only steps are workflow sub-workflow steps, no cost block of its own, calling a child this box has solid observed history for — confirm plan.estimate.basis == "observed" and partial == false. And separately, confirm a parent with a genuine uncosted step of its own (e.g. a for_each task step with no cost) plus a priced/observed child still reports partial: true (the #242 case, unchanged).

  4. dkackman commented on Sep 21, 2026

    @dkackman
    OwnerAuthor

    Verified over MCP (tester agent, model opus via provider anthropic).

    Ran, all with workspace: "hysteresis" (the two stored parents live there, not in default — the issue body didn't say, for the record):

    • validate_workflow(name="hysteresis") → plan.estimate = {minutes: 6.6, basis: "observed", partial: false, unpriced: []} (was unknown/partial: true).
    • validate_workflow(name="hysteresis-ltx2.5") → {minutes: 2.5, basis: "observed", partial: false, unpriced: []}.
    • Inline pure-composition parent (id: qa-268-inline, one workflow step → templates/minimax/video-with-audio, no cost) → basis: "observed", partial: false, minutes: 6.6. So the roll-up works for an inline definition too, not only stored ones.
    • The validate_workflow's cost estimate is confidently wrong for composed workflows with no cost block #242 neighbour, inline qa-268-mixed: same composing step plus an own extract_frames task step with no cost → basis: "unknown", partial: true, unpriced: ["qa-268-mixed"], minutes 6.6 still carried. Distinction preserved as described.
    • Child directly, validate_workflow(name="templates/minimax/video-with-audio") → basis: "observed", minutes: 6.6, runs: 2, measured_on: "NVIDIA GeForce RTX 3090".

    Matches expected:. One small gap, not blocking this: the rolled-up parent reports runs: null and measured_on: null while the child it inherited from reports runs: 2 / measured_on: "NVIDIA GeForce RTX 3090" — filing that separately.

    Adding the proposed regression case to regression-suite-complete.md next.

  5. added
    status:verifiedTester confirmed the fix via a real MCP call
    and removed on Sep 21, 2026
  6. added
    field-reportFiled from Don's own dw sessions (real use), not the harness
    on Sep 24, 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

    field-reportFiled from Don's own dw sessions (real use), not the harnessowner: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