You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
#866 stage C: the inherited estimate scales by steps and canvas too #908
Stage C of #866. Section "Stage C" (and "The design → Inherited path") of the plan: #866 (comment). The plan comment (v2) is authoritative; this restates it.
claude-opus-5-5 / anthropic, lead
Builds
_scale_past_template (dw/server/deps.py) also multiplies by the num_inference_steps ratio and the width × height ratio, read the way pipeline_frames reads num_frames. The inherited path and stage A then give the same minutes for the same request.
inherited_differences._COST_SETTINGS (dw/vram_inheritance.py) gains attention backend, cache and LoRA, read from the keys the H3 template's steps set. They are reported in differs and turn on low_confidence.
Owes
tests/test_inherited_cost.py: a 30-step and a 1344x768 inline workflow.
A consistency test: an inline copy of reference-to-video and the template itself, with the same arguments, give the same minutes within rounding.
Docs: the ARCHITECTURE estimate row and SERVER.md, if the inherited wording changes.
Deploy
Server restart.
Passes when
The repro passes: an inline H3 Ref2VA clone at 30 steps and 1344x768, in a workspace where the template has history, gives basis: "inherited" scaled by both ratios with scaled naming them, and it agrees with the template path within 10%. The stage also needs every pending: #<this issue> case the tester writes to pass.
Stage C shipped: develop @ 7ab6440 (merge of feat/866-C-inherited-scaling @ 2566e6c). Deploy: deployed develop @ 7ab64404, healthy.
claude-opus-5-5 / anthropic, lead
Plan items covered
_scale_past_template scales by num_inference_steps and width × height (dw/server/deps.py). Both are read per pipeline step by the new pipeline_values (dw/vram_inheritance.py; pipeline_frames is now a wrapper around it), the same way num_frames is read, and compared by the mean per step. The scaled text names each axis that moved, e.g. scaled from templates/minimax/reference-to-video: inference steps 30 vs 9 per step; canvas 1344x768 vs 960x544 per step. A step-count or canvas value that can't be compared (non-numeric, or set on one side only) is withheld with the template and the reason (canvas differs and cannot be compared), the same way frames were already handled.
_COST_SETTINGS gains attention backend (attention_backend), cache (cache) and LoRA (loras): the keys the H3 template's step sets. They are reported in differs.
low_confidence: an inherited estimate whose differs is non-empty now carries low_confidence: true (dw/plan.py_observed).
Tests (tests/test_inherited_cost.py):
a 30-step inline workflow, a 1344x768 one, the two combined through the caller's arguments, a bucket already at 30 steps (not scaled twice), a canvas that can't be compared (withheld), and the plan's inherited + scaled answer;
attention, cache and LoRA each named in differs, and low_confidence set in the plan;
consistency: the shipped reference-to-video.json priced through the catalog path versus an inline copy priced through the real inherited_observed, at 30 steps and 1344x768, agree within 0.1 min.
Docs: the ARCHITECTURE Inherited cost row (plus the consistency test as a pin) and the inherited wording in SERVER.md.
Deviation from the plan
The plan says the three new settings turn on low_confidence. I turn it on for any non-empty inherited differs, which also covers offload and quantization. That matches stage B, where an unscalable shift (weights_dtype) flags the catalog figure. Before this stage, an inherited figure that differed only in offload or quantization carried no low_confidence.
Notes for verification
Before deploying, lem quoted the template path at num_inference_steps 30, 1344x768 as 51.9 (derived, from the curated 7.88). The template's default bucket observed 7.8 min over 33 runs, so the inline clone should quote about 7.8 × 30/9 × 1.976 ≈ 51.4 (inherited), within 10%.
The full pytest run has 17 failures (test_plugin_skills Kandinsky6, test_examples, test_component_type_errors). All 17 also fail on develop without this change, in the local environment. ruff is clean.
Architecture review queued by the loop driver: this hand-off changed dw/ or dw_mcp/ on develop (de2c55c7b4..e31b224d88: dw/plan.py dw/server/deps.py dw/vram_inheritance.py). The reviewer checks it against docs/ARCHITECTURE.md before the tester verifies.
Architecture review: bounced (`de2c55c7..e31b224`, commit 2566e6c; `dw/plan.py`, `dw/server/deps.py`, `dw/vram_inheritance.py`, `docs/ARCHITECTURE.md`, `docs/SERVER.md`), checked against `docs/ARCHITECTURE.md` and the stage C guardrails, item 3. The issue isn't labelled `arch-approved`.
claude-opus-5-5 / anthropic, reviewer
Finding: a second owner (blocks)
Map row: The estimate (`dw/plan.py`: `estimate`, `_tempered`) gives proportional scaling along `num_inference_steps`, `width`/`height` and `num_frames` to `scale_curated`: "a run moving `num_inference_steps`, `width`/`height` or `num_frames` … scales it in proportion (`scale_curated`)".
`_scale_past_template` (`dw/server/deps.py`) now does that arithmetic itself, without calling `scale_curated`. It has its own `factor *= mean_mine / mean_theirs` for inference steps and canvas pixels, plus its own axis wording through `_size`/`_described`. The change's own updated Inherited cost row says the two are "the same proportions `scale_curated` applies". The only thing keeping them equal is a test (`TestTheTemplateAndAnInlineCopyAgree`), not the code. They have already drifted in wording: `scale_curated` writes `steps 30 vs 9` / `frames …`, while the inherited path writes `inference steps 30 vs 9 per step` / `frame count …`. A later change to the scaling rule (a fixed load/decode term, say, which `scale_curated`'s docstring already flags as missing) would then have to be made in two places.
What would resolve it: keep the part that is specific to the inherited path, which is reading each axis per pipeline step through `pipeline_values` and averaging. Then pass the two sets of means to `scale_curated` as `defaults` (the bucket's) and `effective` (the workflow's), and take the factor and `axes` from it. That way one rule prices both paths, and the consistency test checks that the paths agree rather than holding two copies together. The pipeline-step-count ratio and the "cannot be compared" withholding stay in `deps.py`, since no map row assigns them elsewhere. If you think mixed canvases need pixel means instead of per-dimension means, that argues for widening `scale_curated` to handle it, not for a second copy. The alternative is for Don to label the issue `arch-approved`.
Checked, no finding
Build vs. buy: nothing hand-rolled that a `pyproject.toml` dependency provides.
The map: the Inherited cost row is updated in the same change. It names the new axes, the `differs` settings and `low_confidence`, and it pins the consistency test. `pipeline_values` / `sets_differently` stay inside `dw/vram_inheritance.py`, which already owns the row, so no new owner appears.
Context: no `CLAUDE.md` touched. The rationale is in the docstrings of `_scale_past_template`, `inherited_differences`, `pipeline_values` and `_COST_SETTINGS`.
The `low_confidence`-on-any-`differs` deviation is a behavior question for the tester and Don, not an architecture one, so I haven't judged it here.
Stage C re-shipped after the second C-F485 bounce (differs: ["LoRA"] on a copy that declares lora_alpha: null): develop @ 2ce7f2a (merge of feat/866-C-inherited-scaling-6 @ e243ec7). Deploy: deployed develop @ 2ce7f2ab, healthy after 5s.
claude-opus-5-5 / anthropic, lead
Cause
The tester's third candidate was the right one: number spelling. The template's lora_scale is 1.0. A client's JSON round trip respells it as 1, and inherited_differences compared each side's loras as json.dumps text, so "scale": 1 and "scale": 1.0 compared unequal. I reproduced it locally. The shipped template with only lora_scale set to the int 1 gives ["LoRA"] at f1bc2e9, and [] with 1.0. The missing top-level keys and the prompt don't affect it.
That helper moves from dw/plan.py (_same_number) to dw/variables.py (same_number), so both callers share one owner. Importing it from plan.py would have made a cycle (plan → validation → vram_inheritance). The fingerprint's behaviour doesn't change.
A real difference is still named: lora_scale: 0.5 gives ["LoRA"].
Test
test_a_client_round_trip_differs_in_nothing (tests/test_inherited_cost.py) builds the tester's W:
the shipped template with its integral floats respelled as ints;
cost, cost_drivers, summary, vram_estimate and variable_constraints dropped;
seed 42 and a new prompt.
It runs W through inherited_observed and build_plan, and asserts basis: "inherited", no differs and no low_confidence. The test fails without the fix. It does not go over the MCP transport itself: the respelling happens in the client, and an in-process Python client wouldn't reproduce it.
Plan items
Unchanged from the last hand-off: the steps and canvas scaling, _COST_SETTINGS gaining attention, cache and LoRA, the consistency test, and the SERVER.md low_confidence sentence. The C-F484 figures don't change.
Checks
Full pytest: the same 17 Kandinsky6 failures develop already has, and nothing else.
Architecture review queued by the loop driver: this hand-off changed dw/ or dw_mcp/ on develop (d0fb3f4596..2ce7f2ab27: dw/plan.py dw/variables.py dw/vram_inheritance.py). The reviewer checks it against docs/ARCHITECTURE.md before the tester verifies.
Architecture review: pass (d0fb3f4..2ce7f2a; #908's commit is e243ec7, which touches dw/plan.py, dw/variables.py, dw/vram_inheritance.py and tests/test_inherited_cost.py). claude-opus-5-5 / anthropic, reviewer. I checked it against docs/ARCHITECTURE.md and stage C guardrails item 3.
What I read
_carried (dw/vram_inheritance.py) now serializes each value through same_number before json.dumps, so 1 and 1.0 collapse to one entry. A bool is untouched, and a real difference (0.5) still differs.
Second owner: none. The change creates one owner for integral-float canonicalization, which the fingerprint and the inherited comparison now share, instead of a copy in vram_inheritance.py. I grepped dw/ for other is_integer() canonicalizers. variable_constraints.py:134, variables.py:376 and task_domains.py check integrality for validation and don't respell values, so they aren't the same rule.
Build vs. buy: nothing in pyproject.toml applies.
Map: no row names the helper. The Bound acknowledgement row (ARCHITECTURE.md:97) names dw/plan.py: fingerprint, which still owns the fingerprint and still lives there. The Inherited cost row (:106) still describes differs correctly: by-value comparison doesn't change what is listed. No rule moved owners: a shared utility moved, so no row needs editing.
Context: no CLAUDE.md touched. The rationale sits in the same_number docstring and a comment in _carried.
Verified: stage C passes. The issue's repro and both pending cases (C-F484, C-F485) pass in one session against develop @ 2ce7f2a, workspace default. claude-opus-5-5 / anthropic, tester
Setup
W is get_workflow("templates/minimax/reference-to-video") with these changes:
seed: 42;
a one-line prompt;
observed, cost, summary, vram_estimate and variable_constraints dropped.
lora_scale: 1.0 and lora_alpha: null are kept. Every call is a validate_workflow, and each variant passes only the named arguments.
C-F484: pass
W inline:basis: "inherited", inherited_from: "templates/minimax/reference-to-video", 7.8 min (M0), runs 33, differs: [], no scaled.
W with {num_inference_steps: 30, width: 1344, height: 768}:basis: "inherited", 51.1 min, scaled: "scaled from templates/minimax/reference-to-video: steps 30 vs 9; canvas 1344x768 vs 960x544".
Expected M0×(30/9)×1.9765 ≈ 51.4, so this is inside ±5%.
By name, {seed: 42, num_inference_steps: 30, width: 1344, height: 768}:basis: "derived", T = 51.9 min, scaled from the curated 7.9.
Inline and template paths differ by 1.5%, inside the 10% bound.
W with {num_frames: 192}:basis: "inherited", 12.0 min, scaled: "...frames 192 vs 124", differs: ["frame count"], low_confidence: true.
Expected 7.8×192/124 ≈ 12.08.
C-F485: pass
W as is:differs: [] and no low_confidence. This was the call that bounced twice; the number-spelling fix holds over the real MCP path.
Activity
dkackman commentedon Oct 15, 2026
Stage C shipped:
develop@ 7ab6440 (merge offeat/866-C-inherited-scaling@ 2566e6c). Deploy:deployed develop @ 7ab64404, healthy.claude-opus-5-5 / anthropic, lead
Plan items covered
_scale_past_templatescales bynum_inference_stepsandwidth × height(dw/server/deps.py). Both are read per pipeline step by the newpipeline_values(dw/vram_inheritance.py;pipeline_framesis now a wrapper around it), the same waynum_framesis read, and compared by the mean per step. Thescaledtext names each axis that moved, e.g.scaled from templates/minimax/reference-to-video: inference steps 30 vs 9 per step; canvas 1344x768 vs 960x544 per step. A step-count or canvas value that can't be compared (non-numeric, or set on one side only) is withheld with the template and the reason (canvas differs and cannot be compared), the same way frames were already handled._COST_SETTINGSgainsattention backend(attention_backend),cache(cache) andLoRA(loras): the keys the H3 template's step sets. They are reported indiffers.low_confidence: an inherited estimate whosediffersis non-empty now carrieslow_confidence: true(dw/plan.py_observed).tests/test_inherited_cost.py):inherited+scaledanswer;differs, andlow_confidenceset in the plan;reference-to-video.jsonpriced through the catalog path versus an inline copy priced through the realinherited_observed, at 30 steps and 1344x768, agree within 0.1 min.inheritedwording in SERVER.md.Deviation from the plan
low_confidence. I turn it on for any non-empty inheriteddiffers, which also covers offload and quantization. That matches stage B, where an unscalable shift (weights_dtype) flags the catalog figure. Before this stage, an inherited figure that differed only in offload or quantization carried nolow_confidence.Notes for verification
num_inference_steps 30, 1344x768as51.9(derived, from the curated 7.88). The template's default bucket observed 7.8 min over 33 runs, so the inline clone should quote about 7.8 × 30/9 × 1.976 ≈ 51.4 (inherited), within 10%.pytestrun has 17 failures (test_plugin_skillsKandinsky6,test_examples,test_component_type_errors). All 17 also fail ondevelopwithout this change, in the local environment.ruffis clean.dkackman commentedon Oct 15, 2026
Architecture review queued by the loop driver: this hand-off changed
dw/ordw_mcp/ondevelop(de2c55c7b4..e31b224d88: dw/plan.py dw/server/deps.py dw/vram_inheritance.py). The reviewer checks it againstdocs/ARCHITECTURE.mdbefore the tester verifies.dkackman commentedon Oct 15, 2026
Architecture review: bounced (`de2c55c7..e31b224`, commit 2566e6c; `dw/plan.py`, `dw/server/deps.py`, `dw/vram_inheritance.py`, `docs/ARCHITECTURE.md`, `docs/SERVER.md`), checked against `docs/ARCHITECTURE.md` and the stage C guardrails, item 3. The issue isn't labelled `arch-approved`.
claude-opus-5-5 / anthropic, reviewer
Finding: a second owner (blocks)
Map row: The estimate (`dw/plan.py`: `estimate`, `_tempered`) gives proportional scaling along `num_inference_steps`, `width`/`height` and `num_frames` to `scale_curated`: "a run moving `num_inference_steps`, `width`/`height` or `num_frames` … scales it in proportion (`scale_curated`)".
`_scale_past_template` (`dw/server/deps.py`) now does that arithmetic itself, without calling `scale_curated`. It has its own `factor *= mean_mine / mean_theirs` for inference steps and canvas pixels, plus its own axis wording through `_size`/`_described`. The change's own updated Inherited cost row says the two are "the same proportions `scale_curated` applies". The only thing keeping them equal is a test (`TestTheTemplateAndAnInlineCopyAgree`), not the code. They have already drifted in wording: `scale_curated` writes `steps 30 vs 9` / `frames …`, while the inherited path writes `inference steps 30 vs 9 per step` / `frame count …`. A later change to the scaling rule (a fixed load/decode term, say, which `scale_curated`'s docstring already flags as missing) would then have to be made in two places.
What would resolve it: keep the part that is specific to the inherited path, which is reading each axis per pipeline step through `pipeline_values` and averaging. Then pass the two sets of means to `scale_curated` as `defaults` (the bucket's) and `effective` (the workflow's), and take the factor and `axes` from it. That way one rule prices both paths, and the consistency test checks that the paths agree rather than holding two copies together. The pipeline-step-count ratio and the "cannot be compared" withholding stay in `deps.py`, since no map row assigns them elsewhere. If you think mixed canvases need pixel means instead of per-dimension means, that argues for widening `scale_curated` to handle it, not for a second copy. The alternative is for Don to label the issue `arch-approved`.
Checked, no finding
The `low_confidence`-on-any-`differs` deviation is a behavior question for the tester and Don, not an architecture one, so I haven't judged it here.
Back to `owner:lead` (this is a `stage`).
56 remaining items
Merge feat/866-C-inherited-scaling-6 (#908)
dkackman commentedon Oct 15, 2026
Stage C re-shipped after the second C-F485 bounce (
differs: ["LoRA"]on a copy that declareslora_alpha: null):develop@ 2ce7f2a (merge offeat/866-C-inherited-scaling-6@ e243ec7). Deploy:deployed develop @ 2ce7f2ab, healthy after 5s.claude-opus-5-5 / anthropic, lead
Cause
The tester's third candidate was the right one: number spelling. The template's
lora_scaleis1.0. A client's JSON round trip respells it as1, andinherited_differencescompared each side'slorasasjson.dumpstext, so"scale": 1and"scale": 1.0compared unequal. I reproduced it locally. The shipped template with onlylora_scaleset to the int1gives["LoRA"]at f1bc2e9, and[]with1.0. The missing top-level keys and the prompt don't affect it.Fix
_carried,dw/vram_inheritance.py) now reads a value by number, not spelling. It uses the same integral-float canonicalization the plan fingerprint got in stage 0 (#866 stage 0: key the plan fingerprint and step cache only by what changes the output #905).dw/plan.py(_same_number) todw/variables.py(same_number), so both callers share one owner. Importing it fromplan.pywould have made a cycle (plan → validation → vram_inheritance). The fingerprint's behaviour doesn't change.lora_scale: 0.5gives["LoRA"].Test
test_a_client_round_trip_differs_in_nothing(tests/test_inherited_cost.py) builds the tester's W:cost,cost_drivers,summary,vram_estimateandvariable_constraintsdropped;It runs W through
inherited_observedandbuild_plan, and assertsbasis: "inherited", nodiffersand nolow_confidence. The test fails without the fix. It does not go over the MCP transport itself: the respelling happens in the client, and an in-process Python client wouldn't reproduce it.Plan items
Unchanged from the last hand-off: the steps and canvas scaling,
_COST_SETTINGSgaining attention, cache and LoRA, the consistency test, and the SERVER.mdlow_confidencesentence. The C-F484 figures don't change.Checks
pytest: the same 17 Kandinsky6 failuresdevelopalready has, and nothing else.ruffis clean.dkackman commentedon Oct 15, 2026
Architecture review queued by the loop driver: this hand-off changed
dw/ordw_mcp/ondevelop(d0fb3f4596..2ce7f2ab27: dw/plan.py dw/variables.py dw/vram_inheritance.py). The reviewer checks it againstdocs/ARCHITECTURE.mdbefore the tester verifies.dkackman commentedon Oct 15, 2026
Architecture review: pass (d0fb3f4..2ce7f2a; #908's commit is e243ec7, which touches dw/plan.py, dw/variables.py, dw/vram_inheritance.py and tests/test_inherited_cost.py). claude-opus-5-5 / anthropic, reviewer. I checked it against docs/ARCHITECTURE.md and stage C guardrails item 3.
What I read
_carried(dw/vram_inheritance.py) now serializes each value throughsame_numberbeforejson.dumps, so1and1.0collapse to one entry. A bool is untouched, and a real difference (0.5) still differs.plan._same_numbermoves verbatim todw/variables.pyassame_number(docstring now cites #866 stage 0: key the plan fingerprint and step cache only by what changes the output #905 and #866 stage C: the inherited estimate scales by steps and canvas too #908).plan._canonical_digestimports it, so the fingerprint behaves the same. The move avoids a plan → validation → vram_inheritance → plan import cycle, as the hand-off says.No finding
vram_inheritance.py. I greppeddw/for otheris_integer()canonicalizers.variable_constraints.py:134,variables.py:376andtask_domains.pycheck integrality for validation and don't respell values, so they aren't the same rule.pyproject.tomlapplies.dw/plan.py: fingerprint, which still owns the fingerprint and still lives there. The Inherited cost row (:106) still describesdifferscorrectly: by-value comparison doesn't change what is listed. No rule moved owners: a shared utility moved, so no row needs editing.same_numberdocstring and a comment in_carried.Waived: none (not
arch-approved).dkackman commentedon Oct 15, 2026
Verified: stage C passes. The issue's repro and both pending cases (C-F484, C-F485) pass in one session against
develop@ 2ce7f2a, workspacedefault. claude-opus-5-5 / anthropic, testerSetup
W is
get_workflow("templates/minimax/reference-to-video")with these changes:seed: 42;observed,cost,summary,vram_estimateandvariable_constraintsdropped.lora_scale: 1.0andlora_alpha: nullare kept. Every call is avalidate_workflow, and each variant passes only the namedarguments.C-F484: pass
basis: "inherited",inherited_from: "templates/minimax/reference-to-video", 7.8 min (M0), runs 33,differs: [], noscaled.{num_inference_steps: 30, width: 1344, height: 768}:basis: "inherited", 51.1 min,scaled: "scaled from templates/minimax/reference-to-video: steps 30 vs 9; canvas 1344x768 vs 960x544".{seed: 42, num_inference_steps: 30, width: 1344, height: 768}:basis: "derived", T = 51.9 min, scaled from the curated 7.9.{num_frames: 192}:basis: "inherited", 12.0 min,scaled: "...frames 192 vs 124",differs: ["frame count"],low_confidence: true.C-F485: pass
differs: []and nolow_confidence. This was the call that bounced twice; the number-spelling fix holds over the real MCP path.attention_backend: "native":basis: "inherited", 7.1 min,low_confidence: true,differs: ["attention backend"].templates/minimax/voice-timbre-reference(3 runs), not reference-to-video. The case doesn't forbid that, so it isn't a finding.cache: {type: "first_block", threshold: 0.05}:basis: "inherited", 7.8 min,low_confidence: true,differs: ["cache"].lora_model_name: null, lora_weight_name: null:basis: "inherited", 7.8 min,low_confidence: true,differs: ["LoRA"].Observation (not a finding against any case)
low_confidence: truewithdiffers: [].differsas well asscaled. Call 2's steps and canvas scaling sets the flag without naming anything indiffers.low_confidenceis meant to come with a reason indiffers, this is a small inconsistency. I'm leaving it to the lead to decide whether it matters.Suite
I removed the
pending: #908line from C-F484 and C-F485 inregression-suite-complete.md, so they are now ordinary cases.