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
Add cross-spec suites (dow suite) for the check x model x domain x temp matrix
`dow aggregate` runs a project's N-way aggregators over a cohort within a SINGLE
spec. A robustness sweep, though, is often a matrix where each cell is its own
spec. `dow suite` aggregates versions drawn from SEVERAL specs at once, declared
in a manifest `specs/<name>.suite.yaml` (its `specs:` list plus the project's own
`evaluation.aggregators`/`plots`). dow still ships none of the coefficients or the
plotting library - the suite only wires in the project's callables.
- spec.py: SuiteSpec dataclass (load/from_dict/to_dict/fingerprint; kind: suite).
- evaluators.py: CohortContext.specs - a parallel per-member spec-name list so an
aggregator can bucket by spec/model/domain/temperature (empty for single-spec).
- service.py: load_suite/list_suites/select_suite (all|latest|<tag>)/aggregate_suite
/suite_aggregations/get_suite_aggregation; spec_files() excludes *.suite.yaml so a
manifest never trips single-spec resolution; composite spec:version member ids.
- store.py: _suites/<name>/ bundle namespace under index["suites"] (kept out of
list_specs); save/list/get_suite_aggregation guard the suite name with
_safe_component on read AND write, and use the atomic writers.
- cli.py: `dow suite` command (+ fix the CLI-local _spec_files() to also exclude
*.suite.yaml, so commit/history/compare/... auto-resolution ignores manifests).
- report.py: print_aggregation is suite-aware (title + N-specs header).
- mcp_server.py: dow_suite tool (server now exposes 15 tools).
- docs/suite.txt (+ regenerated man/dow.1); README/PYPI_README/PROJECT_PLAN.
- tests: test_suite.py (11 - cross-spec select all/latest/tag, bucket-by-spec,
persistence, manifest-not-a-spec, error capture, empty/missing-agg guards, CLI
resolution) + a suite-name traversal test + dow_suite in the MCP tool set.
Bumps dow to 2.1.0.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: PROJECT_PLAN.md
+19-2Lines changed: 19 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -326,6 +326,22 @@ An aggregator receives a `CohortContext` whose `members` is one `EvalContext` pe
326
326
327
327
`dow aggregate`selects the cohort — an explicit list of versions, every version carrying a `--tag`, or the whole history — runs the aggregators, and **persists the result as a durable, git-tracked bundle** under `.dow/aggregations/` (recording the member ids, their fingerprints, the coefficient values, any figures, and a timestamp). A robustness check therefore becomes a citable, reproducible object; `dow aggregate --list` and `--show <id>` retrieve past bundles. Aggregator failures are captured and reported, never fatal.
328
328
329
+
### Cross-spec suites (the matrix)
330
+
331
+
`dow aggregate` operates within a **single** spec. A robustness sweep, though, is frequently a **matrix** — the same check run across several models, domains, or temperatures, where each cell of the matrix is its own spec. **`dow suite`** aggregates versions drawn from **several** specs at once, so the whole matrix collapses into one citable object. The participating specs and the project's own aggregators/plots are declared in a manifest, `specs/<name>.suite.yaml` (a distinct suffix that keeps suites out of the inference-spec code paths, so a manifest never leaks into `dow history` or single-spec resolution):
332
+
333
+
```yaml
334
+
# specs/robustness_matrix.suite.yaml
335
+
name: robustness_matrix
336
+
specs: [check_llama, check_qwen, check_mistral] # specs to draw versions from
337
+
select: all # all | latest | <tag>
338
+
evaluation:
339
+
aggregators: [suite_metrics.py:agg_matrix] # your callables; dow ships none
340
+
plots: [suite_plots.py:plot_matrix]
341
+
```
342
+
343
+
Every member keeps its own captured `config`, and the `CohortContext` gains a parallel **`specs`** list naming each member's spec, so a suite aggregator can bucket by spec / model / domain / temperature. Member ids are composite `spec:version`. `select` chooses the cohort: `all`(every version of each listed spec — the full matrix), `latest` (each spec's newest version), or a tag name (each spec's versions carrying that tag; specs with no match are skipped, and an entirely empty selection is a clear error). Suite runs persist as durable, git-tracked bundles under `.dow/aggregations/_suites/<name>/` — a **separate namespace** from single-spec aggregations — and `dow suite --list`, `--show <id>`, and `--plot` mirror `dow aggregate`. The suite reuses the same aggregator/plot contract, so **dow still ships none of the coefficients or plotting code**.
344
+
329
345
### Pluggable plots (figures as content-addressed artifacts)
330
346
331
347
dow can turn any of these results into a figure without shipping a plotting library. The project references its own plot functions under `evaluation.plots`; each receives a `PlotContext` carrying the analysis `results` to render and a dow-provided `out_dir` to write into, and returns the path(s) of the figure file(s) it produced:
@@ -355,6 +371,7 @@ The commands are task-oriented, not version-control plumbing. Versioning is auto
355
371
| `dow tag <label> [version]` | Tag a version with a free-form label: good, golden, baseline, bad, ... |
356
372
| `dow eval [version]` | Run custom evaluators; compare scores against the previous and last-good versions |
357
373
| `dow aggregate [VERSIONS]` | Aggregate reliability metrics over a cohort of versions (N-way); persist a git-tracked bundle, optionally with figures (`--plot`) |
374
+
| `dow suite [NAME]` | Aggregate versions across several specs (a cross-spec matrix declared in `specs/<name>.suite.yaml`); persist a git-tracked bundle, optionally with figures (`--plot`) |
358
375
| `dow tree` | Visualize evolution: a vertical trunk with branches, as a terminal tree or an exported Mermaid `gitGraph` |
359
376
360
377
Versions are referred to by simple names (`v1`, `v2`), the shortcuts `last` and `prev`, or any label applied with `dow tag` (for example `good`). They form a tree: every commit records its parent, and `dow commit --from v1` starts a new branch from an earlier version. Command output is rendered in the terminal.
@@ -410,7 +427,7 @@ The trunk `v1 -> v2` is the main line; `v3-branch` forks from v1 and continues t
410
427
411
428
### Programmatic and MCP surface
412
429
413
-
The command line is one front end over a headless core (`dow/service.py`); an AI agent gets the same workflow over the Model Context Protocol. The `dow-mcp` server (install with the `mcp` extra) exposes fourteen tools mirroring the commands above - scaffold, read/write a spec, commit, compare, explain, eval, aggregate, tag, history, inspect, tree, and docs - plus read-only resources (`dow://overview`, `dow://docs/<command>`, `dow://specs`, `dow://spec/<name>`) an agent can attach as context. Because both surfaces call the same core, they never drift apart, and both are data-structure agnostic: when a spec sets `embedding_model: none`, the built-in drift, stability, and verdict come back null (`driftEnabled` is false) and the configuration diff plus the project's own metrics carry the analysis. dow itself still ships no metric, statistic, or plotting code.
430
+
The command line is one front end over a headless core (`dow/service.py`); an AI agent gets the same workflow over the Model Context Protocol. The `dow-mcp` server (install with the `mcp` extra) exposes fifteen tools mirroring the commands above - scaffold, read/write a spec, commit, compare, explain, eval, aggregate, aggregate across specs (suite), tag, history, inspect, tree, and docs - plus read-only resources (`dow://overview`, `dow://docs/<command>`, `dow://specs`, `dow://spec/<name>`) an agent can attach as context. Because both surfaces call the same core, they never drift apart, and both are data-structure agnostic: when a spec sets `embedding_model: none`, the built-in drift, stability, and verdict come back null (`driftEnabled` is false) and the configuration diff plus the project's own metrics carry the analysis. dow itself still ships no metric, statistic, or plotting code.
414
431
415
432
---
416
433
@@ -513,7 +530,7 @@ The tool runs entirely offline by default (mock provider and a built-in hashing
513
530
- [ ] `dow explain` attributes a behavioral change to the configuration difference and flags confounded comparisons.
514
531
- [ ] `dow tree` visualizes the version evolution (terminal tree and exported Mermaid), with branches via `dow commit --from`.
515
532
- [ ] Users can plug in custom evaluators (`evaluation.metrics`); `dow eval` runs them lazily, saves the scores with the version, and compares against the previous and last-good versions.
516
-
- [ ] Users can plug in paired comparators (`evaluation.comparators`), N-way cohort aggregators (`evaluation.aggregators`) surfaced by `dow aggregate` as durable git-tracked bundles, and plot functions (`evaluation.plots`) whose figures dow stores as content-addressed artifacts — dow shipping none of the coefficients or plotting code.
533
+
- [ ] Users can plug in paired comparators (`evaluation.comparators`), N-way cohort aggregators (`evaluation.aggregators`) surfaced by `dow aggregate` as durable git-tracked bundles, cross-spec suites (`specs/<name>.suite.yaml`) surfaced by `dow suite`, and plot functions (`evaluation.plots`) whose figures dow stores as content-addressed artifacts — dow shipping none of the coefficients or plotting code.
517
534
- [ ] `dow tag` applies free-form labels (good, golden, baseline, ...) that are usable as version references.
518
535
- [ ] The tool runs end to end offline through mock or local mode.
519
536
- [ ] A rehearsed two-minute demonstration that lands the closing statement.
0 commit comments