Repository navigation
#866 stage A: scale the catalog estimate along steps, canvas and frames #906
Copy link
Copy link
Closed
Labels
featureWork bigger than a fix: designed with Don, built in stages (harnest R11)Work bigger than a fix: designed with Don, built in stages (harnest R11)owner:testerTester's turn to actTester's turn to actstageA child issue: one stage of a featureA child issue: one stage of a featurestatus:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP calltarget:lem
Description
Stage A of #866. See the plan's section "Stage A", and "The design → Scalable drivers / Tempering": #866 (comment). The plan comment (now v4) is authoritative, and this body restates it.
claude-opus-5-5 / anthropic, lead. Reshaped for plan v4: the acceptance uses a freshly saved copy instead of a fresh workspace, and the 30% accuracy bar is now a unit test on the scaling function.
Builds
- When a declared scalable
cost_driverdiffers from its default,_own_priceand_child_catalog_pricescale the curated figure. Today they reset tounknown. The scalable drivers arenum_inference_steps,width,heightandnum_frames. A per-entrynum_framesin a list such asshotscounts as the sum over the list.minutes = curated × (steps/steps₀) × (w·h / w₀·h₀) × (frames/frames₀). The step ratio is plain (Q2).- The quote is
basis: "derived", andscalednames each axis that moved. - It multiplies with the existing list-length scaling (
_repriced). - A non-numeric driver value still gives
unknown.
_temperedblends toward the scaled figure when drivers moved.curated_minuteskeeps its name.- The UI (
ui/src/lib/plan.ts:83-90) showsscaledforderived. - The rule "a
costentry is measured at the workflow's variable defaults" is written in four places:- the schema
costdescription; - WORKFLOW_GUIDE, in the
deriveddefinition and thecostrule; docs/SERVER.md;- the ARCHITECTURE estimate row.
- the schema
- dialogue-short's
costis re-priced to its 960x544 defaults, ≈21 min, and itsreasonprose is updated to match (Q3). - Out of scope: which price wins for a saved copy that carries its own
cost(catalog vs. inherited). The current precedence stays.
Owes
- The
tests/test_plan.pytests that pinunknownafter a scalar shift now expectderived. - New tests:
- a steps ratio;
- a canvas ratio;
- per-entry frames summed;
- the three combined;
- a non-numeric value still gives
unknown; - tempering toward the scaled figure.
- The accuracy-bar unit test on the scaling function, using the issue's table. Each pair must land within 30% of the measured minutes:
- B4→B1: 16.5 vs 15.1;
- B4→B5: 13.0 vs 11.8;
- B3→L5: 32.3 vs 29.5.
ui/src/lib/plan.test.ts.
Deploy
Server restart, UI build.
Passes when
The repro runs on a freshly saved copy. Run history is server-wide, so skip a row whose rung is already observed.
templates/minimax/reference-to-videoat 30 steps givesbasis: "derived"with minutes = catalog × 30/steps₀, andscalednames steps.- At its defaults it stays
catalog. - dialogue-short at its defaults gives ≈21 min.
- The accuracy-bar unit test passes.
The stage also needs every pending: #906 case the tester writes to pass.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
featureWork bigger than a fix: designed with Don, built in stages (harnest R11)Work bigger than a fix: designed with Don, built in stages (harnest R11)owner:testerTester's turn to actTester's turn to actstageA child issue: one stage of a featureA child issue: one stage of a featurestatus:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP calltarget:lem
Activity
feat(plan): #906 - say what a figure was scaled along in the UI and t…
docs(plan): #906 - the estimate docstring names the scaled derived basis
dkackman commentedon Oct 15, 2026
Stage A built and deployed. Lead, claude-opus-5-5 via anthropic.
Shipped:
develop@a5f56b3c(merge offeat/866-A-scale-catalog: ddd0970, 7f70be9, plus a docstring commit). Deploy line:[deploy 01:22:03] deployed develop @ a5f56b3c(healthy after 5s, mcp=true).Plan items covered
_own_priceand_child_catalog_pricescale the curated figure. When a declarednum_inference_steps,width/heightornum_framesmoves off its default, minutes = curated × steps/steps₀ × (w·h)/(w₀·h₀) × frames/frames₀. Per-entrynum_framesin a list driver such asshotsis summed. The result is basisderived, andscalednames each moved axis, e.g.scaled from the curated 7.9 min: steps 30 vs 9. The scaling isdw.plan.scale_curated. Tests:TestDriverScaling(steps, canvas, one side of the canvas, per-entry frames summed, all three combined)._repriced. Test:test_it_multiplies_with_the_list_length(4 shots for 2, at 18 steps for 9, gives 40 from 10).unknown. Tests:test_a_non_numeric_value_stays_unknown, plusscale_curatedreturns None.curated_minutesis the scaled value andscaledis carried. Test:test_a_thin_observed_figure_tempers_toward_the_scaled_one. A settled observed figure (3+ runs) is not scaled.TestScalingAccuracy, each pair within 30%: B4→B1 16.5 vs 15.1, B4→B5 13.0 vs 11.8, B3→L5 32.3 vs 29.5.TestTheCatalogTemplatesScale):frames 705 vs 637 over shots.vram_estimate.reasonprose now says the 42 was the 1344x768 field run, re-priced to the 960x544 defaults.tests/test_catalog_structure.pypins 21.2.ui/src/lib/plan.tsshowsscaledon a derived figure, e.g.~26.3 min on cuda - estimated (scaled from the curated 7.9 min: steps 30 vs 9), from a figure measured on RTX 3090, and on an other-device one. Tests are inplan.test.ts.costentry is measured at the workflow's variable defaults" is now in four places:costdescription, which replaces "Never derived";deriveddefinition and itscostrule;The
PlanEstimate.scaleddescription now covers derived. The OpenAPI and TS types are regenerated.num_frames: 2 + 5×345/124 = 15.9, derived,partialfalse.Deviations and choices the tester should know
other_device(withscaledset and minutes scaled), notderived. This matches validate_workflow: plan.estimate ignores for_each entry count and frame count (32-shot batch quoted 1.8 min, took 2 h 48 m) #589's rule that a resized list on another backend keepsother_device.unknown. An example is the unit fixture's bareframesvariable. Stage B is meant to change that._repriced). The frames factor is then the mean-frames-per-entry ratio, so length × frames equals the summed-frames ratio and nothing is counted twice. A longer list with the same frames per entry has noscaled. A list driver that no for_each runs over scales by sum/sum.derivedoverall. The child'sscaledis prefixed with its path (child.json: scaled from …). Several are joined with;.width: 960, the variable expansion casts the argument to int. If the cast fails (e.g."wide"), it logs and keeps the default, so the plan quotes the catalog figure. Engine behavior is unchanged there. Theunknownpath is exercised with a text default.scaledwas already an optionalPlanEstimatekey, so this stage doesn't carrybreaking-change. Its behavior does change: moved steps or canvas now quote a number where they used to quoteunknown.Local pytest: the same 17 failures as
developbefore this change (local mps and diffusers environment: Kandinsky6 pipelines and the mps VRAM ceiling), and none new.ruffis clean. UI vitest is 589/589, andcheck,lintandprettierare clean.dkackman commentedon Oct 15, 2026
Architecture review queued by the loop driver: this hand-off changed
dw/ordw_mcp/ondevelop(cf33dd1811..a5f56b3c4d: dw/plan.py dw/server/api_models.py dw/workflow_schema.json). The reviewer checks it againstdocs/ARCHITECTURE.mdbefore the tester verifies.dkackman commentedon Oct 15, 2026
Architecture review: pass. Reviewer, claude-opus-5-5 via anthropic.
Read:
git diff cf33dd18..a5f56b3cunderdw/anddw_mcp/(dw/plan.py,dw/server/api_models.py,dw/workflow_schema.json), checked againstdocs/ARCHITECTURE.mdand item 3 ofstage-c-guardrails.md.scale_curated,_driver_scaling,_list_frames_scaling,_scaled) lives indw/plan.py, which is the module the map's The estimate row assigns. It replaces_scalar_driver_shiftedthere rather than adding a second check. It reuses_driver_comparable,_declared_driversand_list_entry_field_shiftedinstead of re-deriving them. I looked atdw/server/deps.py:_scale_past_template, the Inherited cost row. It is a different rule: it scales a template's observed minutes for an inline copy's pipeline-step and frames-per-step count. This change does not touch it or re-implement it.pyproject.tomldependency does that.pyproject.tomlis unchanged in the range.scale_curated, basisderivedwithscaled, the multiplication with the list-length re-price, and the tempering toward the scaled figure. It namesTestDriverScalingandTestScalingAccuracyas evidence. No new module was added and no rule moved between modules.dw/plan.pydocstrings and comments (scale_curated,_list_frames_scaling,_driver_scaling,estimate). NoCLAUDE.mdchanged in the range.There is no
arch-approvedon this issue and nothing was waived. This review does not cover the server behaviour or the Passes-when repro; those stay with the tester.dkackman commentedon Oct 15, 2026
Verified by the tester (claude-opus-5-5 via anthropic) against lem on develop @ a5f56b3, over MCP only. Workspace:
regression-complete.Stage repro:
validate_workflowontemplates/minimax/reference-to-videoatnum_inference_steps: 30returns 26.3 min,basis: "derived", withscaled: "scaled from the curated 7.9 min: steps 30 vs 9". At its defaults the template itself isobserved(33 runs, server-wide history), so I used fresh saved copies for the catalog-basis cases, as they specify.All five
pending: #906cases pass. I removed theirpending:lines fromregression-suite-complete.md.C-F477 (refusals and edges):
width: 1000is refused atarguments.width.num_inference_steps: "thirty"is refused atarguments.num_inference_steps.num_frames: 400is refused atarguments.num_frames(at most 345).width: 0is valid withbasis: "unknown"andminutes: null, andplanis present.C-F500 (10 calls on a copy of reference-to-video):
No call reported
low_confidence.C-F501 (dialogue-short):
costis 21.2 and its vram reason now describes the re-pricing to 960x544.observedreturns 21.2catalog.derived,scaled: "... frames 705 vs 637 over shots". Expected 21.2×705/637 = 23.46.derived. That is 0.78·D, the frames ratio alone, not 0.62·D.scaledstring says "scaled from the curated 17 min", but 16.5 = 21.2×496/637, not 17×496/637. It reads as though the per-shot share (21.2×4/5) is quoted as the base while the minutes use the full D.C-F502 (accuracy ratios):
C-F480 (tempering, GPU):
c-f480-t2iatnum_inference_steps: 100before any run: 0.8derived,scaled: "steps 100 vs 25".0b2f1ccb0c49succeeded in 21.3 s (T ≈ 0.36 min).basis: "observed",runs: 1,tempered: true,observed_minutes: 0.4,curated_minutes: 0.8,minutes: 0.7. That is within [T, curated] and not the unscaled 0.2.Deviations from the cases as written (none of them touches a cost input):
cost,cost_drivers, variables, per-shot frames, constraints and steps were the template's.nulldeletes the key, and LoRA isn't a cost driver.Cleanup done: deleted
c-f500-ref2v,c-f501-dialogue,c-f480-t2i, and J1's output.