# plakat 2.0.0 — roadmap (major cycle, planning)

1.0.0 was "the cut" (confidence / stability / polish). Since then 1.1–1.21 added the map
generator, the `plakat ui` terminal UI, and the power-user loop; **1.22.0** landed a
source-wide stability pass (40 bugs fixed — see `BUGFIX_PLAN.md`). 2.0.0 is the next major
milestone. This file opens as a **planning landing pad** — scope is decided with the user,
not pre-committed.

Status: `[ ]` open · `[x]` done · `[~]` in progress · `[⏸]` blocked · `[?]` needs a decision.

## Carried-over known work (from the 1.22.0 stability pass)

Concrete, already-scoped — the honest backlog to clear early in 2.0.

- [ ] **T5 pad attention mask** (BUGFIX 1.2) — PixArt/SD3 encode captions without masking
      pad tokens; a correct fix means the vendored T5 + threading a mask through every
      DiT/MMDiT cross-attention block. **Needs the diffusers reference-comparison harness**
      to verify it doesn't regress the (currently correct) models.
- [ ] **Transformer-trainer resume warm-up** (BUGFIX 4.1 follow-up) — apply the SD/SDXL
      resume LR warm-up to the sd3 / pixart / cascade training loops too.
- [ ] **Scenario style+persona lazy-load** (BUGFIX 3.2 full fix) — evict stylize/portrait
      pipelines per task-kind instead of holding all co-resident (currently: preflight
      warning only).
- [ ] **compvis output-block LoRA mapping** (BUGFIX 5.6) — map attention-less up-block
      upsamplers correctly (currently fail-safe under-apply).

## Decisions needed

- [?] **Map cross-machine determinism** — the docs claim byte-stable across machines, but
      terrain/coast math uses non-correctly-rounded libm transcendentals (last-ULP varies by
      platform). **Either** narrow the wording to "byte-stable on a fixed platform" **or**
      vendor fixed-point implementations of the determinism-critical transcendentals (as was
      done for the bitmap font). Decide before spending effort.
- [?] **What makes it 2.0** — the theme. Candidates below; pick with the user.

## Chosen theme — `plakat verify` (RFC_VERIFY.md)

Promote the diffusers reference-comparison method (which fixed every silent-noise bug)
into a first-class, **self-contained** subcommand. Shipped tool stays pure-Rust/HF-only;
diffusers lives only in an offline authoring step whose golden tensors are frozen on HF.
Full design + impact analysis: [`RFC_VERIFY.md`](RFC_VERIFY.md).

- [x] **Phase 0 — framework + Tier 0 (zero downloads).** `src/verify/` + `plakat verify`
      `[--tier N] [--json]`; Tier 0 structural/determinism checks (CFG batch-layout invariant
      guarding BUGFIX 1.1, map byte-stability); higher tiers report as skipped. Green offline
      + in CI, no external data.
- [x] **Phase 1 — comparison engine + capture abstraction (self-contained, tested).**
      `compare` (corr/cosine/max-abs + thresholds), the `Manifest` format + loader, golden
      safetensors loading, the `tier1` runner (`compare_against_goldens`), and the
      `TensorTap`/`CaptureBag` capture abstraction — 13 unit/integration tests, no model
      needed. `verify --tier 1` reports the pilot set as *ready, awaiting goldens*.
- [x] **Phase 1b/2 — wire `TensorTap` capture points into the pipelines + author goldens.**
      Naturally coupled: each capture point is wired and its golden authored together
      (offline diffusers harness → HF), so the capture is verified against the reference the
      moment it lands. Pilot: sd15/sd21/sdxl/sd35/pixart/cascade (+ animatediff, Tier-0 only).
      **All six authored, verified vs diffusers 0.38, and hosted on `vulogov98/plakat-verify`.**
      The harness earned its keep: it caught the **SDXL CLIP-L pad-token bug** (padded `"!"`/id 0
      instead of EOS → `clip.encoded` corr 0.991; fixed `3a28f67`, now 1.0). See
      `tools/reference/correspondence.md` for the CLIP pad-token rule.
      - [x] **Authoring harness scaffolded** — `tools/reference/` (excluded from the crate):
        `dump.py` + per-family dumpers (sd15 worked example, others stubbed), `fixtures.py`,
        and `correspondence.md` (the diffusers↔plakat module map). Emits the exact
        `goldens.safetensors` + `manifest.json` the Rust side parses.
      - [x] **Capture wired across the families + Tier-1 loop closed** — `capture_intermediates`
        on `t2i` (`clip.encoded`, `clip_g.pooled`, `vae.decoded`), `sd3` (`pooled_y`), `pixart`
        (`dit.pos_embed`), `cascade` (`clip_g.pooled`); `tier1::run_model` dispatches by variant
        (SD / SD3 / PixArt / Cascade). `vae.decoded` uses a shared LCG latent (no RNG-matching).
        AnimateDiff: CFG-layout guarded in Tier 0; a numerical motion tap is a follow-up (not
        alias-loadable). `--golden-dir` + `--device`; all additive; offline green. Real dumpers
        for sd15/sdxl/sd35/pixart/cascade.
      - [x] **HF-dataset fetch** — `verify --tier 1` fetches goldens from the HF dataset
        (default `vulogov98/plakat-verify`, `PLAKAT_VERIFY_DATASET` override) when no
        `--golden-dir`; 404s → clean skip until hosted. `hf::get_dataset_file` +
        `verify::golden`. Pure-Rust, no new deps.
      - [x] **Run locally + validate + host** — authored all six via `dump.py`, validated each
        against plakat (`--golden-dir`), and pushed to `vulogov98/plakat-verify`. Results:
        sd15 `clip.encoded`/`vae.decoded` corr 1.0; sd21 0.99999/1.0; **sdxl** `clip.encoded`
        1.0 (after the pad-token fix)/`clip_g.pooled` 0.99997; **pixart** `dit.pos_embed` 1.0;
        **stable-cascade** `clip_g.pooled` 0.99997; **sd35-medium** `pooled_y` 0.99998 (concat
        order correct). Pooled vectors use max_abs 0.15 (CLIP-G accumulation noise; corr carries
        correctness). `verify --tier 1 --model <m>` now passes for everyone, self-contained.
      - [x] **Denoiser/transformer-core + motion taps (all 7 families)** — beyond conditioning:
        `unet.out` (SD1.5/SDXL) + `unet.mid` (SDXL), `dit.block0` (PixArt), `mmdit.block0`
        (SD3.5), `stage_c.out` (Cascade — coarse, OOD-sensitive deep UNet), `motion.block0`
        (AnimateDiff, via the flag-load path). All corr 1.0 vs diffusers 0.38 except Cascade
        (0.989 coarse). Block taps use a shared deterministic caption/context
        (`verify::deterministic_tensor`). Hosted on `vulogov98/plakat-verify`.
- [x] **Phase 3 — Tier 2 end-to-end perceptual gate.** Renders the fixture via the REAL
      generate path (encode→denoise→VAE→PNG) and compares to a frozen golden PNG (regression
      gate = plakat's own deterministic output). Determinism via `PLAKAT_VERIFY_DET_INIT` (LCG
      init, candle CPU RNG isn't seed-reproducible) + DDIM → byte-identical run-to-run.
      Self-contained metrics (mean-abs + global SSIM, no torch). sd15 256²: SSIM 1.0 / mean_abs
      0.0. `src/verify/tier2.rs` + `golden::resolve_golden_image`.
- [x] **Phase 4 — CI, regression baselines, docs.** `.github/workflows/ci.yml` runs Tier 0
      (`plakat verify --tier 0`) on every push/PR (zero downloads, ~0.2s, non-zero exit fails);
      an opt-in `verify-models` job (workflow_dispatch, `model` input) runs the weight-backed
      Tier 1/2 fetching goldens from HF. The hosted goldens ARE the regression baselines.
      Operator guide in `Documentation/VERIFY.md` (running, authoring/hosting, adding a capture
      point, threshold calibration). Makes the map-determinism invariant + every capture point
      cheap to re-verify. **RFC_VERIFY complete — the 2.0.0 theme is delivered end-to-end.**

## Other candidate themes (deferred / secondary)

- [ ] **Library / API stabilization** — a documented, semver-stable Rust crate API.
- [ ] **Performance pass** — profile hot paths (VAE decode, attention, weight load).
- [ ] **Flux in the UI** — unblock when capable hardware is available.
