Multi-Goal
Multi-objective optimization via Design of Experiments. Tune competing metrics at once — generate a DOE matrix, fit effects, pick the best config.
Install
claude plugin marketplace add tyroneross/multi-goal
claude plugin install multi-goal@multi-goal
# or standalone:
uv run python scripts/doe.py
The Problem
Most “make it faster” work optimizes one number and silently regresses another — latency drops but bundle size grows, or test coverage climbs while build time balloons. Tuning one factor at a time misses interactions between factors, and eyeballing a few configs doesn’t tell you which factor actually moved the needle.
What I Built
Part of the design-of-experiments optimization pattern (see /toolkit/patterns/design-of-experiments) — here: extracted and extended from build-loop’s single-metric
optimizeas a pure Python/NumPy CLI, with the greedy fallback triggered by estimated cost rather than reserved for the single-factor case.
A multi-objective Design of Experiments optimizer, extracted and extended from build-loop’s single-metric optimize. Given a set of factors (up to 11) and competing objectives, it generates a DOE matrix — full factorial, fractional factorial, or Plackett-Burman depending on factor count — runs the experiments, fits per-objective effects, and selects the best configuration.
Selection supports three strategies: weighted scalarization, Derringer-Suich desirability (each objective gets a target and a tolerance), and the Pareto frontier (surface the non-dominated set and choose). When a full design is too expensive, it falls back to a greedy single-factor autoresearch loop. NumPy is the only runtime dependency; it runs as a Claude Code / Codex plugin or as a standalone CLI.
Worked Example
Using the competing-objectives case named in “The Problem” — latency and bundle size, where cutting one commonly grows the other:
Objectives: minimize latency, minimize bundle_size — the pair “The Problem” calls out as the kind of trade-off single-metric tuning silently regresses.
Factors: up to 11 factors can be entered per run; factor count decides which design gets generated — full factorial, fractional factorial, or Plackett-Burman.
Selection: the three strategies read the same matrix differently. Weighted scalarization collapses latency and bundle_size into one score and returns the best row. Derringer-Suich desirability requires each objective to clear its own target/tolerance band before a row is eligible. The Pareto frontier surfaces every non-dominated row — no config beats another on both metrics — and leaves the final pick to whoever reads it.
Fallback: if the selected design is too expensive to run in full, the optimizer drops to the greedy single-factor autoresearch loop instead of running a partial matrix.
Results: ⚠️ no benchmark yet — this write-up does not publish measured latency, bundle-size, or run-count figures from an actual optimization run.