Repository navigation
idea: sweep runs + experiment tracking - one shot across N configurations, with structured assessments in notes #872
Copy link
Copy link
Closed
1 / 11 of 1 issue completedClosed
1 / 11 of 1 issue completed
Copy link
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 actstatus:plan-approvedDon approved the feature plan (Don only)Don approved the feature plan (Don only)status:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP calltarget:mini-aiFound against a non-lem server (DW_TARGET=mini-ai); Don triagesFound against a non-lem server (DW_TARGET=mini-ai); Don triagesverified-on:mps
Description
Problem
The quality matrix (31 entries) was run with a local script, tools/ladder.py, that:
- builds one workflow per rung from a tuple
(width, height, weights, lora, steps, attention, *opts)where opts are shot name, seed, prompt variants, andcache/compiledicts; - waits for the server to be idle (int8 can't run two at once), submits with a
note, polls, appends{rung, job, status, minutes, file}toladder.jsonl; - then a second script,
tools/push_notes.py, rebuilds 83 notes frommatrix.json(run note: config + minutes + score; file note: the assessment; workspace note: the ramp).
That's general: "render this shot under these configurations, one factor at a time, and keep the results together" is how every quality or speed question gets answered.
Proposal
- Sweep:
run_workflow(..., sweep={"variable": [values...]} | [{...override set...}, ...])or atemplates/sweepthat takes a base workflow + list of argument overrides. Runs sequentially (respecting host RAM), one run dir per variant, same seed, each run noted with its overrides. Returns a table of job, minutes, file. - Structured notes: notes are free text today. The matrix needed fields:
score(1-5),howie_face,pat_face,staging,speech,defects,judged_by. Letset_noteaccept an optional JSON object (or tags + score) solist_gallery/list_jobscan filter/sort by score and a sweep can render a results table server-side. - Pair with
compare_outputs(separate issue) for the grids.
Questions
- Sweep as a server feature vs a skill + client script? The server knows host RAM and queueing; a client script has to poll for idle.
- Should a sweep be a first-class "experiment" object (list of runs + its matrix), or just runs sharing a tag?
Source: H3 quality matrix on lem (2x RTX 3090 24 GB, 125 GB host RAM), workspace h3-quality, Known Issues ep 6 shots, seed 42. Full data and per-run assessments: ~/testing/opus/known-issues/quality/matrix.json, report quality/REPORT.md; every run in h3-quality carries a note with its config, minutes and score. Related: #861 (follow-up experiments).
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 actstatus:plan-approvedDon approved the feature plan (Don only)Don approved the feature plan (Don only)status:verifiedTester confirmed the fix via a real MCP callTester confirmed the fix via a real MCP calltarget:mini-aiFound against a non-lem server (DW_TARGET=mini-ai); Don triagesFound against a non-lem server (DW_TARGET=mini-ai); Don triagesverified-on:mps
Activity
dkackman commentedon Oct 14, 2026
Plan v2: sweeps and experiment tracking
v2 (Don approved 2026-10-14): item 5 now describes the latest-run-only step cache (#890's C-F469 bounce), the acceptance repeat is of the latest variant, and item 2 keeps the template's
costblock.Lead agent, model
claude-opus-5-5viaanthropic.Verdict: build smaller, as one docs stage
Build a "Running a sweep" section in the
workspacesguide (docs/WORKSPACES.md, whichget_guideserves). It writes down the looptools/ladder.py+tools/push_notes.pydid by hand, using the tools dw already has:save_workflowthe base, with each factor as a variable;run_workflowper variant, withargumentsfor the overrides, a pinned seed, and anotenaming the overrides;wait_for_jobbefore submitting the next variant;list_jobs(workspace=)for the table;set_notefor the assessment.Cut, and what would bring each part back:
A server sweep (
sweep=onrun_workflow, a batch object, a multi-job wait): don't build. Every piece of it already exists as one call per variant. The two things the script really fought are other issues' work:Comes back if a sweep session reports, as a field report, that one call per variant cost real context or time after feature: H3 templates - expose attention_backend + cache everywhere, and a quality tier preset that sets the coupled knobs together #865 and bug: two int8 H3 jobs on two cards OOM-kill the host - dispatch is VRAM-aware only, and the earlier job was the one killed #869 land.
Structured notes (JSON or score fields on
set_note, filter and sort by score): defer. A note already holds 4,000 characters of text.get_jobandget_gallery_metadatareturn it in full, and listings clip it at 200. The guide sets a first-line convention (Q2), so a score reads at a glance even in a listing. The server change is wide:clean_noteraises TypeError on a non-string, andread_notessilently drops one (dw/notes.py:40,:68-71);note TEXTcolumn (dw/server/job_history.py:134);strnote fields inapi_models.py, plus the generated UI schema;NoteEditor.svelteand five UI pages;list_pagereads notes only after its limit cut (dw/server/jobs.py:629), so sorting by score means reading every run or adding a column;"note"already means a hint string in six MCP responses, so a structured value under that key would be ambiguous.Comes back if a second experiment, beyond
h3-quality, needs server-side ranking by score, or if idea: compare_outputs MCP tool - face-crop grids, contact sheets and diff metrics across runs #871's grids need to order by score.An "experiment" object: don't build. A workspace already is one.
h3-qualityholds the whole matrix, its notes, and the ramp as its workspace note.Value
h3-qualitymatrix (31 rungs, 83 notes, 63 jobs as idea: compare_outputs MCP tool - face-crop grids, contact sheets and diff metrics across runs #871's plan counted) was run entirely outside dw.Build cost
Stage A: ~$1.5–3 (docs plus a guide-section test).
Inertia
SURFACE_BUDGEThas 0.5 tokens of headroom (tests/test_mcp_server.py:1594), so any new parameter forces a ceiling raise.Reversibility
Fully reversible: it is text.
Cheaper alternatives
arguments+noteonrerun_job(Q1).JobManager.rerun(arguments=)already takes overrides (dw/server/jobs.py:505), and the route already admits and checks bound acknowledgements against whatever arguments it is given (dw/server/routes/jobs.py:414-440). The change is small.save_workflowand thenrun_workflowby path already gets that, so it isn't in v1.Overlap
compare_outputs, in plan review): the grids and metrics for judging a sweep. The guide section links to it once it ships, and needs nothing from it now.Proposed follow-up
None. The sweep found no unused surface in this area.
Problem and non-goals
Problem: "Render this shot under N configurations, one factor at a time, and keep the results together" is how every quality or speed question gets answered, but dw has no written method for it. The one matrix so far needed two local scripts.
Non-goals:
Design (Stage A)
Add
## Running a sweeptodocs/WORKSPACES.md, soget_guide("workspaces", section="Running a sweep")serves it. It covers:save_workflowa copy withvariable:references, keeping the template'scostblock soplan.estimatestill has a basis. It notes that{}keeps a dtype value a string.arguments. Change one factor per variant. Quotevalidate_workflow'splan.estimateper variant, since a factor can change the cost, and get one go-ahead for the whole list.run_workflowper variant, with anotewhose first line is the overrides (steps=20 attention=sage). Callwait_for_jobbefore submitting the next. Say why: bug: two int8 H3 jobs on two cards OOM-kill the host - dispatch is VRAM-aware only, and the earlier job was the one killed #869, host RAM. Drop that sentence once bug: two int8 H3 jobs on two cards OOM-kill the host - dispatch is VRAM-aware only, and the earlier job was the one killed #869 ships.reused. Going back to an earlier variant after another has run re-renders it. Each card's worker has its own cache, and a restart empties it. A re-render is expected, not a failed variant.list_jobs(workspace=…)for job, status and note, andget_jobfor timing and files.set_noteon the output file, using the Q2 convention.keep_outputthe winner, and put the conclusion in the workspace note.Owed:
dw_mcp/.Deploy: server. The guide text ships with the server checkout that
get_guidereads, so lem pulls the new text.Acceptance intent (tester, over MCP)
get_guide("workspaces", section="Running a sweep")returns the section, and every tool it names exists inlist_tools.steps= 4 / 8 / 12, seed pinned) in a freshqa-*workspace gives:list_jobs(workspace=…);get_jobarguments;reused, as the guide says.set_noteon one output, in the Q2 form, reads back in full inget_gallery_metadata, and its first line shows inlist_gallery.Order and dependencies
Stage A is the whole feature. It does not wait on #869 or #865: it describes today's behaviour, and the #869 sentence is removed when that fix ships. If #865 is declined, step 2's "save a copy with variables" path covers the H3 knobs.
Risks
Questions
rerun_jobgainsarguments(merged over the original's) andnote?save_workflowplusrun_workflowcovers it.SURFACE_BUDGETis raised by the measured amount. Acceptance: a rerun witharguments={"steps": 8}runs at 8 steps with the original seed and roots, and a bad variable name is refused likerun_workflowrefuses it.score N/5 · judged_by <who>, then free text: onekey: valueline per facet (faces, staging, speech, defects).WORKSPACES.md, because a sweep is runs, notes and workspaces.workflowsguide's Authoring a workflow from an agent section. It is already long, and an agent already reads it before every run.Reply in comments and hand back with
owner:lead. Approve by addingstatus:plan-approvedyourself. No agent may set it.dkackman commentedon Oct 14, 2026
Review: approve as written.
I checked the plan's claims against develop:
clean_noteraisesTypeErroron a non-string, and notes are capped at 4000 characters (dw/notes.py:26).JobManager.rerunalready takesarguments=(dw/server/jobs.py:505).WORKSPACES.mdhas no sweep section yet. Its Runs section already documents"reused": trueon unchanged reruns, which the fourth-variant acceptance check relies on.tests/test_mcp_guides.py,tests/test_server_guides.py).The plan is right to cut the server sweep. Its two real pain points are #869 (host RAM) and #865 (accelerator knobs as variables), and serializing jobs inside a sweep feature would only have hidden #869.
Q1: no.
save_workflowplusrun_workflowcovers it, and the MCP surface has 0.5 tokens of headroom.Q2: take the default,
score N/5 · judged_by <who>as the first line.judged_bymatters, because an agent can't judge motion or audio. If the convention drifts, that drift is the evidence for structured notes.Q3:
WORKSPACES.md.claude-opus-5-5 / anthropic, for Don
dkackman commentedon Oct 14, 2026
Stages for plan v1, in build order:
## Running a sweepindocs/WORKSPACES.md, plus the guide-section test. Blockers: none.This is the first decomposition, so the stage is new and needs cases. The plan's Acceptance intent is observable over MCP (
get_guide,run_workflowx3 + a repeat,list_jobs,get_job,set_note,get_gallery_metadata,list_gallery). Don approved v1 as written and his answers match the plan's defaults (Q1 no, Q2score N/5 · judged_by <who>, Q3WORKSPACES.md), so the plan did not need a new version. Handing to the tester for specs.Lead agent, model
claude-opus-5-5viaanthropic.20 remaining items
dkackman commentedon Oct 14, 2026
Spec for plan v2, written from the approved plan alone (no source or branch read). The one stage, #890, was reshaped, so only its v2 changes got new text. All cases are in
regression-suite-complete.mdand keeppending: #890.#890 stage A (Running a sweep section in
WORKSPACES.md):C-F467 (amended): point 5 now expects v2's latest-run-only caching:
reused;It now also checks that the save-a-copy path says to keep the template's
costblock (v2 item 2). It is a finding if the section still says any earlier same-seed variant is a cache hit.C-F468: unchanged.
C-F469 (amended, as Don approved on this issue):
steps=12isreusedand returns variant 3's file.steps=8afterwards is not reused. It renders a new file.list_jobs(workspace=).reusedassertion applies when the repeat'sdevicematches variant 3's, which is always so on one card. On a different card, a re-render is what the guide says to expect.C-F470: unchanged.
No dropped stages, so there is no retirement request. No security case: the plan loosens no boundary.
Note, not blocking: I edited C-F467 and C-F469 in place instead of filing a suite request. Don approved the C-F469 amendment explicitly. The C-F467 change restates the approved v2 item 5 for a pending case of the reshaped stage. Both source lines say so.
Tester, model
claude-opus-5-5viaanthropic.dkackman commentedon Oct 14, 2026
Lead agent, model
claude-opus-5-5viaanthropic. Close-out.## Running a sweepindocs/WORKSPACES.md), verified on mps (mini-ai, develop @ c243b99), C-F467–C-F470 all pass. One bounce (C-F469), which was the plan's gap and was re-planned as v2.docs/proposals/complete/sweeps-complete.md(commit fa92492, merged todevelopat 29d4c4c). It supersedesdocs/proposals/sweeps-and-comparison.md(Feature: parameter sweeps, batch rerun and side-by-side comparison #379), now deleted;todo.mdlists the feature under Shipped since the ranking. Docs only, nothing to deploy.verify: run every case whose
source:names one of this feature's stages, and close the parent if they all pass.dkackman commentedon Oct 14, 2026
Verified on mps on mini-ai.lan (develop @ 29d4c4c), by claude-opus-5-5 via anthropic.
Feature-parent close-out: ran every suite case whose
source:names stage #890 (C-F467 through C-F470 inregression-suite-complete.md) exactly as written, over MCP. All pass.C-F467, guide.
Running a sweepis listed in the guide index'ssections. The exact and loose (running a sweep) lookups return the same content, and all eight points are present:costblock;score 4/5 · judged_by …note convention.Every tool it names exists. It doesn't invent a
sweep=parameter or a structured note field.C-F468, three-variant sweep. Saved
sweep-basein workspaceregression-sweep, with astepsvariable and thecostblock kept. Validated steps=4/8/12; each was clean, with its own fingerprint and plan.estimate 0.2 min. Ran all three at seed 42:C-F469, cache reuse.
reused: trueand returned variant 3's file.list_jobslists the six jobs newest first, each with its note's first line.C-F470, notes.
get_gallery_metadataandlist_gallery,·intact.score 3/5 · judged_by claude-opus-5-5 ·) is accepted. Metadata returns the full text. The listing clips it at about 200 characters withnote_truncated: true, and the clipped text still startsscore 3/5 · judged_by.a note is at most 4000 characters, got 4001, and the stored note is unchanged.keep_output→asset:sweep-winner.jpg. The workspace note was set and appears on theregression-sweepentry oflist_workspaces.Cleanup. Deleted the asset, all six runs (
delete_output(job_id=…)), thesweep-baseworkflow and the workspace.list_workspacesno longer listsregression-sweep.Two observations, neither a failure:
got 4195) showed my count was off; the limit was not at fault. With the corrected text, the boundary holds exactly.regression-sweephad been created and deleted earlier on this server,list_jobsalso returns 12historical: trueentries from those deleted instances. Counting the non-historical entries gives exactly 3 and then 6, as the cases expect. I'm not filing anything for this.