feat: flatten output into variants/ and intermediates/

Drop per-job subdirs for phone-friendly Syncthing layout with
stem-suffixed filenames; keep web state in meta/.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Frank Schwenk
2026-07-18 14:52:47 +02:00
parent 9a9a3e3afe
commit b925b151f0
11 changed files with 289 additions and 220 deletions
+7 -5
View File
@@ -26,11 +26,12 @@ def build_remix_options(assets: FilterAssets) -> dict[str, list[str]]:
}
def create_remix_variant(job_id: str, original_suffix: str, choice: RemixChoice) -> dict:
def create_remix_variant(job_id: str, choice: RemixChoice) -> dict:
"""Compose exactly one variant from explicit choices and append it to
the job's manifest. Raises PipelineError on failure (caller should show
the job's meta. Raises PipelineError on failure (caller should show
it to the user, no half-written manifest entries are ever created)."""
paths: JobPaths = pipeline.job_paths(job_id, original_suffix)
stem = pipeline.sanitize_stem(job_id)
paths: JobPaths = pipeline.job_paths(stem, ".jpg")
if not paths.original.exists() or not paths.rembg.exists():
raise PipelineError("Original oder Rembg-Bild fehlt fuer diesen Job — Remix nicht moeglich.")
@@ -42,10 +43,11 @@ def create_remix_variant(job_id: str, original_suffix: str, choice: RemixChoice)
if choice.bg_blend not in assets.blend_modes or choice.fg_blend not in assets.blend_modes:
raise PipelineError("Unbekannter Blend-Modus.")
manifest = pipeline.read_manifest(job_id) or {
"job_id": job_id,
manifest = pipeline.read_manifest(stem) or {
"job_id": stem,
"original_file": paths.original.name,
"rembg_file": paths.rembg.name,
"source_stem": stem,
"created_at": pipeline.now_iso(),
"variants": [],
}