← back to Wallco Ai

SEAM-WAVE-RUNBOOK.md

83 lines

# Seam-fix scale-up — wave cadence runbook

**Decision of record:** DTD verdict **C** (unanimous 3/3, 2026-06-11). Scale the
native-seamless seam-fix from the 5-root sample to the remaining flagged roots in
**waves of ~20 with a curate checkpoint between every wave** — never blanket-apply.
The 261-row luxe revert (2026-05-25) is why this rule exists.

## Why waves (not "batch all")
The hard edge gate (`verify-edge-seamless.py`, PASS-both-axes) guarantees the
*tiling* property in code, but it is blind to *aesthetic* regression and to
fibre-composite failures on root archetypes absent from the 5-root sample. Five
roots can't represent 85+ heterogeneous roots (busy vs. sparse, light vs. dark
ground, fine-line vs. mass silhouette). Waves turn an 80-root mistake into a
20-root one at near-zero added cost — Steve curates every row regardless.

## The pipeline (what a wave actually does)
Each root → **ControlNet edge-anchor** (preserves the motif so it doesn't drift)
→ **circular-pad native-seamless tiling** (zero post-hoc smear) → **composite onto
a real seamless woven-fibre ground** (grasscloth/raffia/linen/sisal/paperweave) →
**verify-edge-seamless.py** (must PASS both axes). Every candidate lands as a NEW
id, `is_published=FALSE`, `parent_design_id=<root>`. **Roots are never overwritten.**

The smear techniques are retired for visible output: do NOT use `make_seamless.py`
or `force-edge-seamless.py`.

## The gate (enforced by `scripts/seam-wave.sh`)
1. **Curate + approve the 5-root sample first.** Open the seam-fix curator
   (`http://127.0.0.1:9905/seam-fix-curator.html`), eyeball the ControlNet sample
   (roots 2662, 54266, 54076, 54610, 53896). When the direction looks right:
   ```bash
   touch data/seam-sample-approved.flag    # GATE 1 — without this, no wave runs
   ```
2. **Build the manifest** of remaining roots (see below). GATE 2 refuses if empty.
3. **Run one wave at a time.** The runner never auto-loops — the pause between
   invocations IS the checkpoint.

## Build the manifest
The 85 roots already in the curator each have a PASS candidate — they're **done**.
`data/seam-wave-roots.txt` is for the remaining FAIL roots not yet processed.
Generate the list from a seam scan of published roots, then write the FAIL ids
(one per line), excluding any root that already has a PASS candidate in
`data/seam-fix-queue.jsonl`:

> **Pre-filter for ANIMAL-FORWARD roots (proven, 2026-06-12).** The
> ControlNet-anchored pipeline only rescues roots where the animal is the
> *dominant* structure. Glassware-dominant / animal-minority roots are
> unrescuable — every clean-seamless roll loses the animal (subject-gate=NO over
> 24+ attempts on 54076 orangutan + 54266 frog, now retired). When building the
> manifest, drop roots where the animal isn't the dominant element. Retired roots
> live in `data/seam-wave-exclude.txt` and `seam-wave.sh` auto-subtracts them, but
> pre-filtering at manifest-build time saves wasted waves.
```bash
# example — confirm the right scanner + exact output format next session
python3 scripts/edges-batch-scan.py        # or fuzzy_seam_scan.py / seam_break_scan.py
# → collect FAIL root ids → data/seam-wave-roots.txt (one per line)
```

## Confirm the generator name
`seam-wave.sh` calls `SEAM_GENERATOR` (default `scripts/controlnet-anchored-redo.py`).
The ControlNet-anchored generator was being finalized in the same session this
runbook was written — **confirm the final script name + that it accepts
`--ids a,b,c`** before the first real wave:
```bash
SEAM_GENERATOR=scripts/<confirmed-generator>.py bash scripts/seam-wave.sh --dry-run
```

## Operate
```bash
bash scripts/seam-wave.sh --status     # progress + gate state, no generation
bash scripts/seam-wave.sh --dry-run    # which roots the next wave would do
bash scripts/seam-wave.sh              # run the next wave (gates must pass)
# → curate the wave → if quality held, run it again for the next wave
# → if quality dropped, STOP and fix the pipeline
```
Tune wave size with `WAVE_SIZE=20`. State lives in `data/seam-wave-state.json`
(reset with `rm`), audit trail in `data/seam-wave-ledger.jsonl`.

## Hard constraints (always)
- Roots sacred — never overwrite; new id, `is_published=FALSE`, `parent_design_id=root`.
- Never publish to live; the settlement gate still governs publish.
- A candidate that doesn't PASS both axes is never selectable/publishable.
- Generation stays PAUSED until GATE 1 (sample approved) — this is deliberate.