Repository navigation
bug: MagCache calibrate ratios never reach an MCP/REST client - docs say they're logged #891
Description
Carved out of #875 (plan v1, approved: Q1 yes). Item 4 of #875, a MagCache rung for H3, can't finish over MCP until this lands.
Filed by the lead agent, model claude-opus-5-5 via the anthropic provider.
The bug
docs/ACCELERATION.md:78 and the calibrate description in dw/workflow_schema.json (~line 808) say a mag cache with calibrate: true "logs the measured ratios … paste that array into mag_ratios". No MCP or REST client can see them:
- At the last step, diffusers'
_advance_step(hooks/mag_cache.py:379-394in the installed venv)print()s the ratios, logs them at INFO ondiffusers.hooks.mag_cache, and clears the list in the same call. - The worker is a spawned process whose stdout goes to the
dw.serveconsole (dw/worker_manager.py:73-81). - The file handler is attached only to the
dwlogger (dw/log_setup.py:23-39), anddiffuserssits at WARNING, so the INFO line is dropped. - Job events come only from explicit
emit_*calls (dw/events.py:246-249), soget_job,get_job_eventsandexport_jobcarry no trace of the ratios.
The fix (no new surface)
While a mag cache with calibrate: true runs, capture the ratio list before diffusers clears it. Emit it as:
- an existing
logevent, and - a job
warning, so it survives the 200-event history trim.
Message: MagCache calibration (N steps): [ … ] — paste into mag_ratios.
- Capture. Reading after the forward is too late. Either snapshot the state's list each forward and take the final value, or capture the
diffusers.hooks.mag_cachelog record. You pick. A unit test pins the choice against the installed diffusers. - CFG (Don's addition). Under CFG, dw nests
cache_context("cond")andcache_context("uncond"), each with its ownMagCacheState, so a CFG run yields two ratio lists whilemag_ratiostakes one array. Emit both, each labeled with its context, or emitcondonly and say so in the message. State which you chose in the docs. - Docs. Fix
docs/ACCELERATION.md:78and the schema'scalibratedescription to say where the ratios appear: job warnings and events. Include the CFG behavior. - No new event type, MCP tool, field or syntax.
Where: this probably lands in stateful_cache_context (dw/pipeline_processors/components.py, ~833-864). #867 stage 2 hooks the same mag_cache_leader_block_hook state there. Per Don (Q2), the two are independent: whichever lands second rebases.
Owes
- A unit test for the capture against the installed diffusers, covering CFG (two contexts).
- The two doc fixes above.
- A restart of
dw.servebefore verification. The persistent worker caches engine code.
Passes when
On a running server, over MCP:
- Run a small cached step with a CFG template (an SD template, not a guidance-distilled one such as Flux), ~10 steps,
cache: {type: mag, calibrate: true}.get_job.warningsandget_job_eventscarry the calibration message. Each emitted list has length equal to the step count, and the CFG labeling matches the docs. - Run the same step without
calibrate. No calibration message appears.
Activity
dkackman commentedon Oct 14, 2026
triage: work — no new surface (existing
logevent + job warning), likely instateful_cache_context(dw/pipeline_processors/components.py); independent of #867 stage 2 per Don. Needs a server restart before verification. (claude-opus-5-5, anthropic)fix(cache): #891 - mag calibrate ratios reach job warnings and log ev…
style: #891 - ruff format
dkackman commentedon Oct 14, 2026
Fixed in a27aaab (+ format-only 95813b3) on develop, deployed to lem @ 95813b3 (03:02, healthy).
What changed
captured_mag_calibration(dw/pipeline_processors/components.py), entered around each pipeline call inpipeline.py. Active only when the transformer's cache config hascalibrate: true. It attaches a handler to thediffusers.hooks.mag_cachelogger and catches the "Calibration Results" record, which diffusers emits before clearing the list.emit_logand anemit_warning:MagCache calibration (N steps) [cond]: [...] — paste into mag_ratios.[cond]/[uncond]from the active cache context. The cond message adds a note that cond is the usual choice. A non-CFG run has no label.docs/ACCELERATION.mdand the schemacalibratedescription now say the ratios appear as job warnings and log events, and describe the CFG behavior.Tests: two new cases in
tests/test_cache_blocks.pydrive the real installed-diffusers mag hooks (cond + uncond) and check both messages, plus no message without calibrate. Not exercised end-to-end on a GPU. The full suite has 9 failures intest_examples.py(Kandinsky6 classes missing from installed diffusers); they also fail on the prior commit.To verify: per Passes-when: ~10-step SD (CFG) step with
cache: {type: mag, calibrate: true}, then without calibrate. Expect two lists of length = step count, labeled cond/uncond.(claude-sonnet-5-5, anthropic)
dkackman commentedon Oct 14, 2026
Architecture review queued by the loop driver: this hand-off changed
dw/ordw_mcp/ondevelop(39d59692b4..95813b3deb: dw/pipeline_processors/components.py dw/pipeline_processors/pipeline.py dw/workflow_schema.json). The reviewer checks it againstdocs/ARCHITECTURE.mdbefore the tester verifies.17 remaining items
dkackman commentedon Oct 14, 2026
Fixed again, on a stronger model (
claude-opus-5-5, anthropic) than the sessions behind the earlier fixes. Fix commit6e506baemerged todevelopas 8b9dad7 and deployed to lem at 2026-10-14 05:25 (systemd restart, healthy).Why Z-Image showed nothing. The capture code was fine. On Z-Image the cache never attached at all:
ZImageTransformer2DModelhas no diffusersenable_cache()(it isn't aCacheMixin). dw skipped it with alogger.warningthat only went to the server log. So neither the calibration message nor its step-count warning could appear.What changed
dw/pipeline_processors/components.py: skipping a transformer withoutenable_cache()is now a job warning,<step>: MagCacheConfig was not applied: ZImageTransformer2DModel does not support diffusers' enable_cache(), so this step runs uncached. It goes throughemit_warning, soget_job.warningsshows it. It covers every cache type, not only mag.dw/cache_blocks.json: registersQwenImage21TransformerBlock, so Qwen-Image-2.1 (a CacheMixin running two-pass CFG incond/uncondcontexts) can take mag/first_block caches.docs/ACCELERATION.mdand the schema'scalibratedescription:"use_kv_cache": falseunder mag/first_block: its own KV cache drops text tokens after step 0, and the step-to-step residual comparison then fails.test_cache_on_transformer_without_enable_cache_warnsintests/test_cache_blocks.py.Confirmed on lem through the deployed server (MCP
run_workflow, worker path), as asked:94aa0f241febtrue_cfg_scale: 4.0,negative_prompt,use_kv_cache: false,cache: {type: mag, calibrate: true}get_job.warningsandget_job_events(log) both holdMagCache calibration (10 steps) [cond]: [10 values] — paste into mag_ratios …and… [uncond]: [10 values] …, plus the "declares 28 but this step runs 10" warningb37f0dbb5692calibrate, the cond list pasted intomag_ratios,num_inference_steps: 10ccc8470cde05(Outputs deleted afterwards.) Mag without
calibrateand withoutmag_ratiosfails in diffusers ("mag_ratiosmust be provided"). That is upstream behavior, so the negative case needs ratios.To verify: use an inline workflow with
component_type: QwenImage21Pipeline,Qwen/Qwen-Image-2.1in bf16,offload: model, andconfiguration.cache: {type: mag, calibrate: true}. Its arguments aretrue_cfg_scale: 4.0, anegative_prompt,use_kv_cache: false,num_inference_steps: 10and 512x512. It takes about 45 s.Proposed regression case (
regression-suite-model-specific.md): the Qwen-Image-2.1 call above. Expect two warnings startingmain: MagCache calibration (10 steps) [cond]/[uncond], each list holding 10 numbers.— claude-opus-5-5 (anthropic)
dkackman commentedon Oct 14, 2026
Architecture review queued by the loop driver: this hand-off changed
dw/ordw_mcp/ondevelop(c96e95318d..8b9dad7f2d: dw/cache_blocks.json dw/media_compare.py dw/pipeline_processors/components.py dw/server/guides.py dw/server/routes/media.py dw/workflow_schema.json dw_mcp/media.py dw_mcp/server.py ). The reviewer checks it againstdocs/ARCHITECTURE.mdbefore the tester verifies.dkackman commentedon Oct 14, 2026
Architecture review: pass (6e506ba, merged as 8b9dad7; only the #891 commit in
c96e9531..8b9dad7funderdw/,dw_mcp/. The #889compare_outputscommits in that range are other work and weren't reviewed here.)I read the
dw/pipeline_processors/components.py,dw/cache_blocks.jsonanddw/workflow_schema.jsondiffs againstdocs/ARCHITECTURE.mdand item 3 ofstage-c-guardrails.md:enable_cache_on_transformerused to be alogger.warning. It now goes out throughdw/events.py'semit_warning, the owner the "Run-time warnings" row names. That matches the no-transformer warning above it from the previous round.dw/acceleration_warnings.py) has no rule about a transformer'sCacheMixinsupport. The new message is a run-time fact about the loaded model, not a copy of a validate-time rule.dw/cache_blocks.py, which feeds diffusers' ownTransformerBlockRegistryand skips any block diffusers already registers. Nothing is hand-rolled.CLAUDE.mdchanged. The schema'scalibratedescription is user-facing documentation, not rationale.Note, not a finding:
components.pyis now about 1,009 lines. That is still past the 1,000-lineSIZE_WARNINGand under the 1,100 ceiling. My earlier note stands: the cache-hook helpers are the natural split if it grows.Nothing was waived (the issue has no
arch-approvedlabel). It goes on to the tester's MCP verification as labelled.Reviewer: model
claude-opus-5-5via theanthropicprovider.dkackman commentedon Oct 14, 2026
Verified. lem: develop @ 92c3952 (includes 8b9dad7). Every run was an inline
run_workflowin workspaceregression-complete. All outputs were deleted afterwards.c2a64b60e158):QwenImage21Pipeline,Qwen/Qwen-Image-2.1in bf16,offload: model,cache: {type: mag, calibrate: true},true_cfg_scale: 4.0,negative_prompt,use_kv_cache: false, 10 steps, 512². It succeeded in about 43 s.get_job.warningsholdsgen: MagCache calibration (10 steps) [cond]: [10 values] — paste into mag_ratios (classifier-free guidance runs two lists; the cond one is the usual choice)and… [uncond]: [10 values] — paste into mag_ratios.get_job_events(kinds=["log"])carries both messages aslogevents (seq 24 and 26).5f9113245108): the same step, but withoutcalibrate, withnum_inference_steps: 10and the cond list pasted intomag_ratios. It succeeded, and its warnings show no calibration or step-mismatch message.3d7e310556b9): the shape from my earlier bounce,ZImagePipelinewith mag + calibrate at 10 steps.get_job.warningsnow carriesgen: MagCacheConfig was not applied: ZImageTransformer2DModel does not support diffusers' enable_cache(), so this step runs uncached. The cache is no longer silently ignored.The served schema/docs wording wasn't re-read in this session. The behavior matches the issue's "Passes when", run on Qwen-Image-2.1 as the hand-off's CFG pipeline in place of an SD template, which can't take a transformer cache.
Tester: model
claude-opus-5-5via theanthropicprovider.dkackman commentedon Oct 15, 2026
Follow-up: #927. On H3, calibration emits nothing because the scheduler runs
num_inference_steps − 1forwards and the capture sets the counter tonum_inference_steps. claude-opus-5-5 / anthropic