* feat(investigations): scaffold #177 LTX23 audio-file lip-sync investigation Reorganize docs/investigations/ into numbered topic folders, each self-contained with narrative + upstream pin + patches + per-run snapshots. Add a generic sync helper that mirrors the dev-sync pattern for any investigation's third-party node modifications. Structure (new): docs/investigations/ 00_LTX23-base-1-step/README.md (rename of ltx-director-4k-transitions.md) 01_LTX23-audio-file-lipsync/ README.md -- problem, mechanism, patches, reversion, promotion upstream.json -- repo + version + pinned commit + sync target env + files patches/ -- source of truth for modified upstream files ltx_director.py -- adds `relay_overrides` multiline JSON input prompt_relay.py -- per-segment sigma per Prompt-Relay paper formula runs/ LOOP.md -- iteration protocol log.md -- rolling table (empty header for now) Sync helper: scripts/sync_investigation_patches.py <NN>_<topic> [--dry-run] - Reads upstream.json for target env var + file list - Backs up the target's current state once per day (<file>.bak.<YYYYMMDD>) - Worktree-aware: falls back to MAIN's .env via git rev-parse --git-common-dir - Prints a two-line report matching scripts/sync_to_dev.py shape - Per-investigation trigger phrase via `trigger:` key (sync-audio for #177) Env: .env.example -- documents new KOLOOK_WHATDREAMSCOST_PATH .env -- local path set Glossary updates (docs/reference/glossary.md): + Investigation folder + JSON file folder + Loop + Run + Investigation patches + sync_investigation_patches.py Closes the workflow gap from #177: MAIN is now the source of truth for investigation patches; the live install is a sync destination only. No manual file copying between iterations — `sync-audio` does it. * chore(ruff): exclude docs/investigations from lint The investigation patches under docs/investigations/*/patches/ are vendored upstream source (WhatDreamsCost-ComfyUI v1.3.2) carried so sync_investigation_patches.py can mirror them into the live install and so iterations can be diff'd against the pinned upstream commit. Linting them would force divergence from upstream and defeat that purpose. Mirrors the existing forks/ exclude precedent. Fixes the CI Lint & Smoke failure on PR #178. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: per-task automation modules + WhatDreamsCost Koolook fork Pivot docs/automations/ from "one folder per model" to "one folder per automation module" so the same diffusion model can host several independent tasks side by side. Replace the parallel docs/investigations/ tree with a fork of WhatDreamsCost-ComfyUI under forks/. Automation modules (new layout) - docs/automations/LTX-2.3/base-1step/ the existing single-stage automation, moved from docs/automations/LTX-2.3/ with its README, findings, and handoff-checklist rescoped to the task. The 4k-transitions backstory that produced the module moves here as backstory/4k-transitions.md. The earlier docs/investigations/experiments/ card PNGs/HTML land in example-cards/. - docs/automations/LTX-2.3/audio-lipsync/ the audio-file lip-sync module previously living under docs/investigations/01_…/. README, handoff, findings stub, backstory/, and runs/{LOOP,log}.md, all referencing the new fork. - docs/automations/README.md + CHEATSHEET.md updated to describe the module-per-task pivot and the new tree shape. - docs/automations/CONVENTIONS.md unchanged (cross-cutting loop contract still holds). WhatDreamsCost Koolook fork (new) - forks/whatdreamscost_koolook/versions/v1_3_2/ UPSTREAM_PIN.yaml pinned to upstream e81223a (v1.3.2), GPL-3.0 verified 2026-05-28. ltx_director.py MODIFIED — adds the relay_overrides multiline JSON widget on LTXDirector. Moved from docs/investigations/01_…/patches/. prompt_relay.py MODIFIED — per-segment σ per the Prompt-Relay paper formula σ = (L − w_eff) / (2 · √ln(1/ε)). Moved from docs/investigations/01_…/patches/. patches.py UNMODIFIED — vendored verbatim from upstream because ltx_director.py imports detect_model_type and apply_patches from it (same precedent as radiance_koolook's color_helpers.py). - Registered as LTXDirector__koolook_v1_3_2 ("LTX Director (Koolook v1.3.2)") so it coexists with an installed copy of upstream WhatDreamsCost-ComfyUI. Wired into the root __init__.py NODE_CLASS_MAPPINGS merge. - forks/forks_manifest.yaml + forks/THIRD_PARTY.md updated with the new entry (attribution, change log, license verified date, exposed node IDs). Removed - docs/investigations/ entire tree retired; its contents either moved to automation modules or to forks/. - scripts/sync_investigation_patches.py no longer needed — fork code lives in the Koolook tree and is synced via the standard dev-sync flow. - KOLOOK_WHATDREAMSCOST_PATH in .env.example same reason. - docs/investigations in pyproject.toml's ruff extend-exclude added in96bf8adto silence lint on vendored patches; no longer needed now that vendored code is under forks/ (already excluded). Docs - docs/reference/glossary.md Investigation folder, Investigation patches, JSON file folder, and the sync_investigation_patches.py entries replaced by Automation module, Backstory, Working folder, and Card. Loop and Run rewritten to point at the new structure. - CHANGELOG.md [Unreleased] describes the restructure + the new fork. Verification - ruff check . → all checks passed - tools/preflight_release.py --skip manager-meta → 42 files parsed; 11 unique node IDs collected including LTXDirector; VAE dispatch branches all OK; fixture workflows still reference all registered Koolook IDs. - pytest → 173 passed, 0 failed. Workflow JSON heads-up The active audio-lipsync workflow LTX-23-audio_tests_v01.json continues to reference the upstream LTXDirector ID. To pick up the new fork's behaviour, swap that node to "LTX Director (Koolook v1.3.2)" (registered ID LTXDirector__koolook_v1_3_2) — sockets and wiring are preserved. The relay_overrides widget appears at the bottom of the new node. Documented in the audio-lipsync README's "Workflow JSON — Koolook node ID" section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(scripts): add dev-sync-audio — scoped sync for audio-lipsync iteration `dev-sync-audio` is a scoped wrapper around `dev-sync` for the [`docs/automations/LTX-2.3/audio-lipsync/`](docs/automations/LTX-2.3/audio-lipsync/) iteration loop. It copies *only* the paths that module touches — the `forks/whatdreamscost_koolook/` subtree and the root `__init__.py` — instead of `rmtree`-ing the whole dest `forks/` and re-copying every Koolook fork on every render. Same `KOLOOK_COMFYUI_DEV_PATH` target, same ComfyUI-Manager restart, same two-line chat-report shape. Changes - `scripts/sync_to_dev_audio.py` (new). Thin wrapper that reuses `sync_to_dev`'s env loader, target validator, restart helper, and chat-report builder, supplying its own `AUDIO_PATHS` tuple. Defaults the `--scope` tag to `"audio-lipsync fork edit"` so the build identifier names this module even when invoked without an explicit scope. - `scripts/sync_to_dev.py` — `sync()` gains an optional `paths` kwarg (defaults to the existing `RUNTIME_PATHS`). Backwards-compatible with every existing call site. - `docs/automations/LTX-2.3/audio-lipsync/README.md` and `runs/LOOP.md` updated to point at `dev-sync-audio` instead of plain `dev-sync` for the iteration step. - Project `CLAUDE.md` — new "Per-module scoped variants" subsection under the existing `dev-sync` section documents the `dev-sync-<module>` pattern, the trigger-name → script-name mapping, and reiterates that the user-initiated-only rule applies verbatim to every `dev-sync-*` variant. Verification - ruff check . → all passed - python scripts/sync_to_dev_audio.py --dry-run -v → would copy: __init__.py would copy: forks/whatdreamscost_koolooke7f3ab4- beautiful-mahavira-ae6da6 would sync 2 entries -> <KOLOOK_COMFYUI_DEV_PATH> (dev-sync-audio) (Confirms scope is correct and the existing dev-sync chat-report shape is preserved.) User-initiated only — never automatic. Trigger phrase: `dev-sync-audio` in chat (also: "copy audio fork", "sync audio fork"). Same rule as `dev-sync` — see project CLAUDE.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(audio-lipsync): only snapshot runs when explicitly kept Every render adds a row to runs/log.md (always). The heavier run-NNN_<label>/ snapshot folders (workflow JSON copy + relay_overrides + patch state + notes) are now created only when the maintainer says "keep", "save run", "save this", or "snapshot" in chat. Without that trigger, the render is just a log row. Why: an active knob sweep can do 10+ renders/hour. Saving a folder per render bloats runs/ fast and most of those folders are noise the moment the next render lands. Cheap log row everywhere, expensive snapshot only for runs worth pinning (knob landed, surprising failure, something heading for findings.md). Changes - docs/automations/LTX-2.3/audio-lipsync/runs/LOOP.md Step 5 split into "always log" + "snapshot only on request". Trigger-detection table updated. Run-labels section reframed (NNN matches log.md row number). Added a one-paragraph "why this retention policy" rationale. - docs/automations/LTX-2.3/audio-lipsync/README.md Folder-map flags run-NNN_<label>/ as conditional. Iteration loop step 5 names the keep / save-run / save-this triggers explicitly. Not a code change. No script edits — the retention rule lives in the agent protocol, not in dev-sync-audio (which stays scoped to code sync, not run management). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(review): harden relay_overrides parser + polish (PR #178 review) Addresses verified findings from the /review-pr pass on PR #178. H1 — relay_overrides values are now type-checked - Allowlist of recognised knobs (`video_strength`, `video_window_scale`, `audio_strength`, `audio_window_scale`, `audio_epsilon`) with explicit float-coercion. Numeric strings ("10") coerce silently; non-numeric values (e.g. "ten") now raise a ValueError naming the offending knob and showing a minimal correct example — instead of a TypeError deep inside `build_segments` arithmetic, or a SUCCESS render at upstream defaults that polluted the A/B iteration log. H2 — malformed JSON no longer silently falls back to defaults - `json.JSONDecodeError`, non-dict JSON (arrays, strings, bare numbers, null), and non-numeric values for recognised knobs all now raise `ValueError` with operator-actionable messages. The only silent fallback is the explicit empty/whitespace case — "use upstream defaults" is the operator's intent there. - Typo'd keys (e.g. `viedo_strength`) log a warning naming the unknown keys + the recognised set, then drop the typo. Previously they were silently retained in the cleaned dict but never queried by `build_segments`, indistinguishable from a default render. Architectural side-effect — shrinks the diff vs vendored upstream - `_parse_relay_overrides` extracted into a stdlib-only sibling module `_relay_overrides.py`. `ltx_director.py` shrinks closer to upstream baseline (one import + one alias instead of a 30-line function body) and is easier to diff against `e81223a`. The parser is also now unit-testable without ComfyUI's `comfy_api` runtime. L5 — tests added (31 cases, all passing) - New `tests/forks/__init__.py` + `tests/forks/test_whatdreamscost_v1_3_2_relay_overrides.py`. - Covers every confirmed failure mode (H1 + H2), the happy path, the comment-key convention, the unknown-key warning, and an allowlist- consistency assertion that fails loudly if `build_segments` ever grows a knob without the parser being updated. - Test module uses `importlib.util.spec_from_file_location` so it can load the parser without walking through the package hierarchy (which would trigger the `comfy_api` import inside `ltx_director.py`). L3 — `_build_line` promoted to public `build_line` - `scripts/sync_to_dev.py` renames the private helper. The underscore alias is kept for one release cycle as a deprecation slot. - `scripts/sync_to_dev_audio.py` switches to `_dev.build_line()`. No behaviour change; chat-report shape is bit-identical to before. L2 — `source_ref` clarified in pin metadata - `forks/whatdreamscost_koolook/versions/v1_3_2/UPSTREAM_PIN.yaml` and `forks/forks_manifest.yaml` both now spell out that `e81223a` is the post-v1.3.2 README-only commit on upstream's `main`, not the v1.3.2 release tag itself. Code is byte-identical to the tagged release; the pin differs only in trailing docs. L1, L4 are explicitly left alone (L1 is dead upstream cruft, kept for minimum-diff; L4 is helper duplication tracked for a separate follow-up issue when a third fork lands). Verification - ruff check . → clean - pytest → 204 passed (173 prior + 31 new parser tests) - tools/preflight_release.py --skip manager-meta → all PASS (static AST extraction still picks up LTXDirector from the fork) - scripts/sync_to_dev_audio.py --dry-run → two-line chat report still emits via the renamed `build_line` helper Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(audio-lipsync): config-driven loop-audio script + module cheat sheet End-to-end automation for one render cycle of the audio-lipsync iteration loop. The chat phrase `loop-audio` invokes a single script that does the whole chain — no manual artifact-shuffling. Scripts (cross-cutting infrastructure at the repo root, like make_card and sync_to_dev; they get lifted into the module folder in the `docs/automations/` → `automations/` move queued for the follow-up PR) - scripts/loop_audio.py Reads its settings from loop_audio.config.json (alongside), auto-discovers the most recent workflow JSON in the ComfyUI user workflows dir (derived from KOLOOK_COMFYUI_DEV_PATH or overridden via KOLOOK_COMFYUI_WORKFLOWS_DIR), extracts the five tracked Text Multilines + LTX Director state + sampler chain, captures fork-state (HEAD SHA + last dev-sync-audio sync info + fork-dir git status), writes the run-NNN_<auto-label>/ snapshot, appends a row to runs/log.md, and chains the card renderer in. Flags mirror sync_to_dev: --dry-run, --label, --no-log, --no-card, --workflow, --config. - scripts/loop_audio.config.json Single source of truth for the customisable settings (job_name, module_path, workflow_pattern, comfyui_workflows_subpath, skip_filename_substring, tracked_multilines, fork_to_track, render_card). Underscore-prefixed keys are inline documentation and ignored by the loader. When the convention shifts — new multiline title, new fork path, different filename pattern — edit the JSON, not the Python. - scripts/make_card_audio.py Audio-lipsync-specific card renderer. Five sections (KNOB STATE, FORK STATE, SAMPLER, BASE notes, OUTCOME) plus an INERT warning band when the workflow's Director is upstream `LTXDirector` with a non-empty relay_overrides. Same palette + font fallback chain as scripts/make_card.py so the base-1step and audio-lipsync card families read as a set. PIL/Pillow added to the `test` optional deps so CI doesn't hit ImportError if any future test touches this script. Docs - docs/automations/LTX-2.3/audio-lipsync/CHEATSHEET.md Module-scoped operating instructions per the cheat-sheet pattern: what the module is for, the chat triggers, the required workflow shape (5 multilines + the Koolook Director variant), the render cycle steps, what lands in each run-NNN_ folder, findings- promotion rule, where every customisable setting lives, and a card-section legend. - docs/reference/glossary.md `Card` rewritten to describe the per-module renderer fan-out (`make_card.py` for base-1step, `make_card_audio.py` for audio-lipsync) — cards no longer live at a single stable `_AI/card.png` path. New `Loop config (per-module)` entry documenting the `<script>.config.json` convention + the required-keys list. - docs/automations/LTX-2.3/audio-lipsync/runs/log.md Header rewritten with column set matching the actual log-row output (Director / relay_overrides / Custom audio / Phase 1 / Phase 2 / Scores / Notes). First real run captured - docs/automations/LTX-2.3/audio-lipsync/runs/run-001_bear_3x-fr_w.audio_upstream_audio-off_vstr10.0/ Baseline reference render — `Bear_3x-FR_w.Audio`, upstream `LTXDirector` still wired into the workflow, use_custom_audio off. Motion 4/5 · Sync 5/5 · Sharp 4/5 per maintainer feedback. The relay_overrides `{"video_strength": 10.0}` is set but inert (Director not yet swapped to the Koolook variant); the card surfaces this with the amber INERT band at the bottom. Captures: workflow.json (185KB), relay_overrides.txt (with INERT note), patch_state.txt (3ffb7b7/15d5688/ clean), notes.md (feedback + scores + mechanical interp), card.png (61KB). Verification - ruff check . → clean - pytest -q → 204 passed, 0 failed - tools/preflight_release.py --skip manager-meta → all PASS - scripts/loop_audio.py --dry-run → identifies the latest workflow, emits the two-line chat-report header, doesn't touch disk - scripts/loop_audio.py (real) → wrote the run-001 folder + card + log row in a single invocation Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(audio-lipsync card): match base-1step visual style 1:1 The first cut of the audio-lipsync card used solid colored header bands and block section panels — visually heavier than base-1step's renderer. Refactored to copy make_card.py's primitives directly: - small uppercase accent-colored section labels (no header bars) - subtle BG_SECTION panel outlines instead of full-width fills - left-accented note boxes (4px coloured bar + dark BG + label inside) for Base · notes, Feedback (video), and the conditional Director note warning - same font fallback chain + sizes as make_card.py (F_SECTION 17pt, F_MONO 19pt, F_NOTE italic 18pt) - oversized canvas + post-render crop matches make_card.py's pattern so cards size to actual content - palette imported in lockstep (BG_OUTER/CARD/SECTION, BORDER, the three accent triples plus the new ACCENT_FORK violet) Two tuning fixes spotted during re-render: - _wrap_text gained a keep_blank_lines flag so prose blocks can collapse the empty separator lines maintainer canvases often have - max_lines bumped on the prose blocks: Base · notes 18 (was 6, truncated the OVERLAY - INFO body), Feedback 6 (was 5), Director note 8 (was 4, truncated mid-sentence) - make_card_audio.py's standalone CLI now loads .env via loop_audio.load_dotenv before rebuilding state, so re-renders show the same FORK STATE lines (MAIN sha + sync sha + scope) that the live loop_audio run captures Visual reference: docs/automations/LTX-2.3/base-1step/example-cards/ run-001-card.png is the layout target. The audio-lipsync card now reads as a sibling of that family — KNOB STATE in amber, FORK STATE in violet, SAMPLER + Base · notes in sky, FEEDBACK + OUTCOME in green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(fork): ship LTX Director timeline-editor JS to the Koolook variant The Koolook variant of LTXDirector was loading as a bare schema — no image strip, no audio strip, no canvas timeline editor — because the upstream timeline-editor JS bundle never came across with the fork. The widget upstream paints onto the node lives entirely in `js/ltx_director.js`; the Python class only declares the inputs. Compounding it, the JS's binding check is hard-coded ``if (nodeData.name === "LTXDirector")``, so even if the bundle had been loaded, it would have skipped our suffixed registry ID (`LTXDirector__koolook_v1_3_2`). Fix: vendor the JS into the fork and rebind it. - web/whatdreamscost_koolook_v1_3_2/ltx_director.js Verbatim copy of upstream's custom_nodes/WhatDreamsCost-ComfyUI/js/ltx_director.js at the pinned commit (e81223a). Two string changes vs upstream: * `name: "LTXDirector"` -> `"LTXDirector_Koolook_v1_3_2"` so the registered ComfyUI extension doesn't collide with the upstream extension (both load in parallel). * `if (nodeData.name === "LTXDirector")` -> `if (nodeData.name === "LTXDirector__koolook_v1_3_2")` so the canvas widget mounts on the Koolook variant only; the upstream extension keeps owning the upstream node. A short comment block at the top documents both deltas. - scripts/sync_to_dev_audio.py AUDIO_PATHS gains `web/whatdreamscost_koolook_v1_3_2` so dev-sync-audio carries the JS into the live install alongside the fork's Python files + root __init__.py. After dev-sync-audio + ComfyUI restart, the Koolook variant mounts the same timeline editor as upstream: image/audio strips, segment dragging, the visual preview row, the [Audio] tag handling, the img_compression/divisible_by widgets. The `relay_overrides` field declared in the Python schema renders at the bottom of the node alongside everything else. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
986 lines
25 KiB
HTML
986 lines
25 KiB
HTML
<!--
|
|
SPDX-FileCopyrightText: 2025-2026 Kforge Labs <https://github.com/malkuthro/ComfyUI-Koolook>
|
|
SPDX-License-Identifier: GPL-3.0-only
|
|
-->
|
|
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Kforge Labs Automation Loop</title>
|
|
<style>
|
|
:root {
|
|
color-scheme: dark;
|
|
--bg: #0e0e0e;
|
|
--panel: #151515;
|
|
--panel-soft: #1a1a1f;
|
|
--panel-warm: #18150f;
|
|
--line: #302f2f;
|
|
--line-strong: #4f4f54;
|
|
--text: #f9fafb;
|
|
--muted: #8f959c;
|
|
--dim: #555b62;
|
|
--blue: #4268ba;
|
|
--blue-bright: #6db4ff;
|
|
--green: #7bcf80;
|
|
--amber: #ffb84d;
|
|
--red: #ff8a8a;
|
|
--violet: #8c7dff;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
scroll-behavior: smooth;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
min-width: 320px;
|
|
background:
|
|
radial-gradient(rgba(150, 150, 150, 0.08) 1px, transparent 1px),
|
|
var(--bg);
|
|
background-size: 13px 13px;
|
|
color: var(--text);
|
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
line-height: 1.5;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
a {
|
|
color: var(--blue-bright);
|
|
text-decoration: none;
|
|
}
|
|
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.hero,
|
|
main {
|
|
width: min(1180px, calc(100% - 32px));
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.hero {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 0.98fr) minmax(320px, 0.82fr);
|
|
gap: 34px;
|
|
align-items: end;
|
|
padding: 52px 0 30px;
|
|
}
|
|
|
|
.eyebrow {
|
|
margin: 0 0 8px;
|
|
color: var(--blue-bright);
|
|
font-size: 12px;
|
|
font-weight: 750;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
h3,
|
|
p {
|
|
margin-top: 0;
|
|
}
|
|
|
|
h1 {
|
|
max-width: 780px;
|
|
margin-bottom: 14px;
|
|
font-size: clamp(38px, 7vw, 72px);
|
|
line-height: 1;
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
h2 {
|
|
margin-bottom: 12px;
|
|
font-size: clamp(28px, 4vw, 46px);
|
|
line-height: 1.06;
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
h3 {
|
|
margin-bottom: 8px;
|
|
font-size: 18px;
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
code {
|
|
padding: 1px 7px;
|
|
border-radius: 5px;
|
|
background: rgb(255 255 255 / 7%);
|
|
color: var(--text);
|
|
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
|
|
font-size: 0.92em;
|
|
}
|
|
|
|
.lead {
|
|
max-width: 720px;
|
|
margin-bottom: 0;
|
|
color: var(--muted);
|
|
font-size: clamp(18px, 2.2vw, 21px);
|
|
}
|
|
|
|
.hero-panel {
|
|
position: relative;
|
|
border: 1px solid var(--line);
|
|
border-radius: 8px;
|
|
background: #101010;
|
|
overflow: hidden;
|
|
box-shadow: 0 22px 60px rgb(0 0 0 / 28%);
|
|
}
|
|
|
|
.hero-panel-head {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
padding: 12px 14px;
|
|
border-bottom: 1px solid var(--line);
|
|
background: #141414;
|
|
}
|
|
|
|
.window-dots {
|
|
display: flex;
|
|
gap: 6px;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.window-dots span {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: var(--dim);
|
|
}
|
|
|
|
.hero-panel-title {
|
|
min-width: 0;
|
|
color: #c9ccd1;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.card-preview {
|
|
padding: 16px;
|
|
}
|
|
|
|
.tracking-card {
|
|
max-width: 420px;
|
|
margin: 0 auto;
|
|
border: 1px solid var(--line-strong);
|
|
border-radius: 8px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tracking-header {
|
|
padding: 14px 16px;
|
|
border-bottom: 1px solid var(--line);
|
|
background: linear-gradient(90deg, #151515, #1b1811);
|
|
}
|
|
|
|
.tracking-header strong {
|
|
display: block;
|
|
font-size: 20px;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.tracking-header span {
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.metric-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 8px;
|
|
padding: 12px;
|
|
}
|
|
|
|
.metric {
|
|
min-width: 0;
|
|
padding: 9px;
|
|
border: 1px solid rgb(255 255 255 / 8%);
|
|
border-radius: 6px;
|
|
background: var(--panel-soft);
|
|
}
|
|
|
|
.metric b {
|
|
display: block;
|
|
color: var(--text);
|
|
font-size: 14px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.metric span {
|
|
display: block;
|
|
color: var(--muted);
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
}
|
|
|
|
.note-strip {
|
|
margin: 0 12px 12px;
|
|
padding: 10px 12px;
|
|
border-left: 4px solid var(--amber);
|
|
border-radius: 5px;
|
|
background: var(--panel-warm);
|
|
color: #e5e7eb;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.score-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 1px;
|
|
border-top: 1px solid var(--line);
|
|
background: var(--line);
|
|
}
|
|
|
|
.score-row div {
|
|
padding: 10px 8px;
|
|
background: #111;
|
|
text-align: center;
|
|
}
|
|
|
|
.score-row b {
|
|
display: block;
|
|
color: var(--green);
|
|
font-size: 17px;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.score-row span {
|
|
color: var(--muted);
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
}
|
|
|
|
.nav-strip {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 10px;
|
|
margin: 0 0 28px;
|
|
padding: 12px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 8px;
|
|
background: rgb(21 21 21 / 82%);
|
|
}
|
|
|
|
.nav-strip a {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
min-height: 34px;
|
|
padding: 6px 12px;
|
|
border: 1px solid rgb(255 255 255 / 8%);
|
|
border-radius: 5px;
|
|
background: var(--panel-soft);
|
|
color: #d8dadd;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.section {
|
|
display: grid;
|
|
grid-template-columns: minmax(250px, 0.78fr) minmax(0, 1.22fr);
|
|
gap: 34px;
|
|
align-items: center;
|
|
padding: 38px 0;
|
|
}
|
|
|
|
.section-copy {
|
|
max-width: 460px;
|
|
padding-left: 16px;
|
|
border-left: 4px solid var(--blue);
|
|
}
|
|
|
|
.section-copy p,
|
|
.band > p,
|
|
.feature-card p,
|
|
.timeline p,
|
|
.caption {
|
|
color: var(--muted);
|
|
}
|
|
|
|
.flow {
|
|
display: grid;
|
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
gap: 10px;
|
|
align-items: stretch;
|
|
padding: 18px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 8px;
|
|
background: #101010;
|
|
}
|
|
|
|
.flow-step {
|
|
position: relative;
|
|
min-height: 142px;
|
|
padding: 15px 12px 14px;
|
|
border: 1px solid rgb(255 255 255 / 9%);
|
|
border-radius: 7px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.flow-step::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
width: 4px;
|
|
background: var(--blue-bright);
|
|
}
|
|
|
|
.flow-step:nth-child(2)::before {
|
|
background: var(--amber);
|
|
}
|
|
|
|
.flow-step:nth-child(3)::before {
|
|
background: var(--green);
|
|
}
|
|
|
|
.flow-step:nth-child(4)::before {
|
|
background: var(--violet);
|
|
}
|
|
|
|
.flow-step:nth-child(5)::before {
|
|
background: var(--red);
|
|
}
|
|
|
|
.flow-step .num {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 28px;
|
|
height: 28px;
|
|
margin-bottom: 12px;
|
|
border-radius: 50%;
|
|
background: rgb(255 255 255 / 8%);
|
|
color: var(--text);
|
|
font-size: 13px;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.flow-step h3 {
|
|
margin-bottom: 7px;
|
|
font-size: 17px;
|
|
}
|
|
|
|
.flow-step p {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.band {
|
|
margin: 30px 0;
|
|
border: 1px solid var(--line);
|
|
border-radius: 8px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.band-head {
|
|
position: relative;
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 0.78fr) minmax(260px, 0.62fr);
|
|
gap: 22px;
|
|
align-items: end;
|
|
padding: 18px 22px;
|
|
border-bottom: 1px solid var(--line);
|
|
background: #131313;
|
|
}
|
|
|
|
.band-head::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
width: 4px;
|
|
background: var(--green);
|
|
}
|
|
|
|
.band-head p:last-child {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
font-size: 16px;
|
|
}
|
|
|
|
.system-map {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
gap: 18px;
|
|
padding: 22px;
|
|
}
|
|
|
|
.folder-panel,
|
|
.contract-panel {
|
|
min-width: 0;
|
|
border: 1px solid var(--line);
|
|
border-radius: 7px;
|
|
background: #101010;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.mini-head {
|
|
padding: 11px 14px;
|
|
border-bottom: 1px solid var(--line);
|
|
background: #171717;
|
|
color: #d8dadd;
|
|
font-size: 12px;
|
|
font-weight: 750;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.folder-tree {
|
|
margin: 0;
|
|
padding: 15px;
|
|
color: #d8dadd;
|
|
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
|
|
font-size: 13px;
|
|
line-height: 1.78;
|
|
white-space: pre-wrap;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.folder-tree .safe {
|
|
color: var(--green);
|
|
}
|
|
|
|
.folder-tree .user {
|
|
color: var(--blue-bright);
|
|
}
|
|
|
|
.node-list {
|
|
display: grid;
|
|
gap: 10px;
|
|
padding: 14px;
|
|
}
|
|
|
|
.node-card {
|
|
padding: 12px;
|
|
border: 1px solid rgb(255 255 255 / 8%);
|
|
border-radius: 6px;
|
|
background: var(--panel-soft);
|
|
}
|
|
|
|
.node-card h3 {
|
|
margin: 0 0 5px;
|
|
color: var(--text);
|
|
font-size: 15px;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.node-card p {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.feature-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
gap: 12px;
|
|
padding: 30px 0;
|
|
}
|
|
|
|
.feature-card {
|
|
position: relative;
|
|
min-height: 168px;
|
|
padding: 18px 16px 16px 20px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 7px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.feature-card::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 auto 0 0;
|
|
width: 4px;
|
|
background: var(--blue);
|
|
}
|
|
|
|
.feature-card:nth-child(2)::before {
|
|
background: var(--amber);
|
|
}
|
|
|
|
.feature-card:nth-child(3)::before {
|
|
background: var(--green);
|
|
}
|
|
|
|
.feature-card:nth-child(4)::before {
|
|
background: var(--violet);
|
|
}
|
|
|
|
.feature-card p {
|
|
margin: 0;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.timeline {
|
|
display: grid;
|
|
gap: 0;
|
|
padding: 36px 0 76px;
|
|
}
|
|
|
|
.timeline-item {
|
|
display: grid;
|
|
grid-template-columns: minmax(260px, 0.76fr) minmax(0, 1.24fr);
|
|
gap: 44px;
|
|
align-items: center;
|
|
padding: 40px 0;
|
|
border-top: 1px solid var(--line);
|
|
}
|
|
|
|
.timeline-item:last-child {
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
|
|
.timeline-item.reverse {
|
|
grid-template-columns: minmax(0, 1.24fr) minmax(260px, 0.76fr);
|
|
}
|
|
|
|
.timeline-item.reverse .timeline-copy {
|
|
grid-column: 2;
|
|
}
|
|
|
|
.timeline-item.reverse .timeline-visual {
|
|
grid-column: 1;
|
|
grid-row: 1;
|
|
}
|
|
|
|
.timeline-copy {
|
|
max-width: 520px;
|
|
}
|
|
|
|
.timeline-copy .eyebrow {
|
|
color: #9ca3af;
|
|
}
|
|
|
|
.timeline-copy h3 {
|
|
max-width: 600px;
|
|
margin-bottom: 16px;
|
|
font-size: clamp(30px, 4vw, 48px);
|
|
line-height: 1.08;
|
|
}
|
|
|
|
.timeline-copy p:not(.eyebrow) {
|
|
margin: 0;
|
|
color: #9ca3af;
|
|
font-size: clamp(18px, 2.1vw, 23px);
|
|
line-height: 1.48;
|
|
}
|
|
|
|
.timeline-copy strong {
|
|
color: var(--text);
|
|
}
|
|
|
|
.timeline-visual {
|
|
margin: 0;
|
|
}
|
|
|
|
.device,
|
|
.terminal,
|
|
.findings-box {
|
|
border: 1px solid var(--line);
|
|
border-radius: 8px;
|
|
background: #101010;
|
|
overflow: hidden;
|
|
box-shadow: 0 18px 46px rgb(0 0 0 / 24%);
|
|
}
|
|
|
|
.device-screen {
|
|
padding: 16px;
|
|
}
|
|
|
|
.comfy-node {
|
|
max-width: 520px;
|
|
margin: 0 auto 12px;
|
|
border: 1px solid var(--line-strong);
|
|
border-radius: 7px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.comfy-node:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.comfy-node-title {
|
|
padding: 9px 12px;
|
|
border-bottom: 1px solid var(--line);
|
|
background: #1b1b1d;
|
|
color: #e6e8ec;
|
|
font-size: 13px;
|
|
font-weight: 750;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.comfy-node-body {
|
|
padding: 11px 12px;
|
|
color: var(--muted);
|
|
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
|
|
font-size: 12px;
|
|
line-height: 1.55;
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
.terminal pre {
|
|
margin: 0;
|
|
padding: 16px;
|
|
color: #d8dadd;
|
|
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
|
|
font-size: 13px;
|
|
line-height: 1.65;
|
|
white-space: pre-wrap;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.terminal .prompt {
|
|
color: var(--green);
|
|
}
|
|
|
|
.terminal .path {
|
|
color: var(--blue-bright);
|
|
}
|
|
|
|
.findings-box {
|
|
padding: 0;
|
|
}
|
|
|
|
.finding-row {
|
|
display: grid;
|
|
grid-template-columns: 140px minmax(0, 1fr);
|
|
gap: 12px;
|
|
padding: 13px 15px;
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
|
|
.finding-row:last-child {
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.finding-row b {
|
|
color: var(--text);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.finding-row span {
|
|
color: var(--muted);
|
|
font-size: 14px;
|
|
}
|
|
|
|
.caption {
|
|
margin-top: 10px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.callout {
|
|
margin: 0 0 54px;
|
|
padding: 18px 22px;
|
|
border: 1px solid rgb(109 180 255 / 30%);
|
|
border-radius: 8px;
|
|
background: rgb(5 47 74 / 35%);
|
|
}
|
|
|
|
.callout p {
|
|
margin: 0;
|
|
color: #d8dadd;
|
|
font-size: 16px;
|
|
}
|
|
|
|
@media (max-width: 1040px) {
|
|
.flow,
|
|
.feature-grid {
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
}
|
|
|
|
@media (max-width: 860px) {
|
|
.hero,
|
|
.section,
|
|
.band-head,
|
|
.system-map,
|
|
.timeline-item,
|
|
.timeline-item.reverse {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.timeline-item.reverse .timeline-copy,
|
|
.timeline-item.reverse .timeline-visual {
|
|
grid-column: auto;
|
|
grid-row: auto;
|
|
}
|
|
|
|
.hero {
|
|
align-items: start;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 560px) {
|
|
.hero,
|
|
main {
|
|
width: min(100% - 20px, 1180px);
|
|
}
|
|
|
|
.hero {
|
|
padding-top: 34px;
|
|
}
|
|
|
|
.flow,
|
|
.feature-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.metric-grid,
|
|
.score-row {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.finding-row {
|
|
grid-template-columns: 1fr;
|
|
gap: 2px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="hero">
|
|
<div>
|
|
<p class="eyebrow">Kforge Labs automations</p>
|
|
<h1>Turn model tests into evidence.</h1>
|
|
<p class="lead">The automation loop keeps ComfyUI renders, workflow JSON, tracking cards, iteration logs, and promoted findings moving through one repeatable path.</p>
|
|
</div>
|
|
<aside class="hero-panel" aria-label="Example tracking card">
|
|
<div class="hero-panel-head">
|
|
<div class="window-dots" aria-hidden="true"><span></span><span></span><span></span></div>
|
|
<div class="hero-panel-title">_AI/card.png</div>
|
|
</div>
|
|
<div class="card-preview">
|
|
<div class="tracking-card">
|
|
<div class="tracking-header">
|
|
<strong>LTX 2.3 Director</strong>
|
|
<span>Run v04 - 2K - seed 12 fixed</span>
|
|
</div>
|
|
<div class="metric-grid">
|
|
<div class="metric"><span>Scheduler</span><b>linear_quadratic</b></div>
|
|
<div class="metric"><span>Steps</span><b>8</b></div>
|
|
<div class="metric"><span>Denoise</span><b>0.40</b></div>
|
|
<div class="metric"><span>Sampler</span><b>euler</b></div>
|
|
<div class="metric"><span>CFG</span><b>1.0</b></div>
|
|
<div class="metric"><span>Audio</span><b>model-gen</b></div>
|
|
</div>
|
|
<p class="note-strip">Delta from base: lower Phase 2 denoise; check whether lip sync survives fast motion.</p>
|
|
<div class="score-row">
|
|
<div><span>Motion</span><b>4/5</b></div>
|
|
<div><span>Sync</span><b>5/5</b></div>
|
|
<div><span>Sharp</span><b>4/5</b></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
</header>
|
|
|
|
<main>
|
|
<nav class="nav-strip" aria-label="Page sections">
|
|
<a href="#loop">Loop</a>
|
|
<a href="#contract">Contract</a>
|
|
<a href="#outputs">Outputs</a>
|
|
<a href="#daily-workflow">Daily workflow</a>
|
|
<a href="#findings">Findings</a>
|
|
</nav>
|
|
|
|
<section class="section" id="loop">
|
|
<div class="section-copy">
|
|
<p class="eyebrow">Mental model</p>
|
|
<h2>One project folder, one repeatable loop.</h2>
|
|
<p>ComfyUI still owns creative iteration. The automation layer gives every render a traceable card and a durable log, so the next decision is based on what actually happened.</p>
|
|
</div>
|
|
<div class="flow" aria-label="Automation loop">
|
|
<article class="flow-step">
|
|
<span class="num">1</span>
|
|
<h3>Tweak</h3>
|
|
<p>Change one knob in ComfyUI and update the run notes.</p>
|
|
</article>
|
|
<article class="flow-step">
|
|
<span class="num">2</span>
|
|
<h3>Save</h3>
|
|
<p>Export workflow JSON into the working folder.</p>
|
|
</article>
|
|
<article class="flow-step">
|
|
<span class="num">3</span>
|
|
<h3>Render</h3>
|
|
<p>Write the video beside the JSON with the same run identity.</p>
|
|
</article>
|
|
<article class="flow-step">
|
|
<span class="num">4</span>
|
|
<h3>Card</h3>
|
|
<p>Run <code>/make-card</code> to create the visual run summary.</p>
|
|
</article>
|
|
<article class="flow-step">
|
|
<span class="num">5</span>
|
|
<h3>Promote</h3>
|
|
<p>Move stable patterns from the iteration log into findings.</p>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="band" id="contract">
|
|
<div class="band-head">
|
|
<div>
|
|
<p class="eyebrow">Data contract</p>
|
|
<h2>The workflow tells the script what matters.</h2>
|
|
</div>
|
|
<p>Three Text Multiline nodes are enough to connect ComfyUI, the repo tools, and the per-project evidence folder.</p>
|
|
</div>
|
|
<div class="system-map">
|
|
<section class="folder-panel" aria-label="Working folder structure">
|
|
<div class="mini-head">Per-project working folder</div>
|
|
<pre class="folder-tree"><span class="user"><working folder>/</span>
|
|
LTX-Director_v04.json
|
|
LTX-Director_v04.mp4
|
|
more JSONs and MP4s
|
|
<span class="safe">_AI/</span>
|
|
<span class="safe">card.png</span>
|
|
<span class="safe">iterations.md</span></pre>
|
|
</section>
|
|
<section class="contract-panel" aria-label="Required ComfyUI nodes">
|
|
<div class="mini-head">Required Text Multiline nodes</div>
|
|
<div class="node-list">
|
|
<article class="node-card">
|
|
<h3>Working_Folder_PATH</h3>
|
|
<p>Absolute path to the project folder. This wins over the repo <code>.env</code> fallback.</p>
|
|
</article>
|
|
<article class="node-card">
|
|
<h3>OVERLAY - INFO</h3>
|
|
<p>Run summary plus a <code>BASE (notes):</code> section for what changed this time.</p>
|
|
</article>
|
|
<article class="node-card">
|
|
<h3>OVERLAY - FEEDBACK</h3>
|
|
<p>Post-render observations and scores like <code>motion: 4/5</code>, <code>sync: 5/5</code>, <code>sharp: 4/5</code>.</p>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="feature-grid" id="outputs" aria-label="Automation outputs">
|
|
<article class="feature-card">
|
|
<h3>Stable card filename</h3>
|
|
<p><code>_AI/card.png</code> is overwritten each run. Wire your NLE to it once and keep comparing.</p>
|
|
</article>
|
|
<article class="feature-card">
|
|
<h3>Append-only log</h3>
|
|
<p><code>_AI/iterations.md</code> grows one row per unique workflow save, with duplicate runs filtered.</p>
|
|
</article>
|
|
<article class="feature-card">
|
|
<h3>Repo stays clean</h3>
|
|
<p>Per-project JSON, MP4, cards, and logs live outside the repo. Docs and findings live here.</p>
|
|
</article>
|
|
<article class="feature-card">
|
|
<h3>Model folders scale</h3>
|
|
<p>Each model gets its own docs folder under <code>docs/automations/</code>; shared rules stay in <code>CONVENTIONS.md</code>.</p>
|
|
</article>
|
|
</section>
|
|
|
|
<section class="timeline" id="daily-workflow" aria-label="Daily workflow details">
|
|
<article class="timeline-item">
|
|
<div class="timeline-copy">
|
|
<p class="eyebrow">Inside ComfyUI</p>
|
|
<h3>Write the run context where the workflow can carry it.</h3>
|
|
<p>Before rendering, update <strong>OVERLAY - INFO</strong>. After watching the video, update <strong>OVERLAY - FEEDBACK</strong>. The saved JSON becomes the source of truth for the card.</p>
|
|
</div>
|
|
<figure class="timeline-visual device">
|
|
<div class="mini-head">Workflow notes</div>
|
|
<div class="device-screen">
|
|
<div class="comfy-node">
|
|
<div class="comfy-node-title">OVERLAY - INFO</div>
|
|
<div class="comfy-node-body">Phase 2
|
|
Scheduler: linear_quadratic
|
|
Steps: 8
|
|
Denoise: 0.40
|
|
|
|
BASE (notes):
|
|
Lower denoise from 0.80 to preserve stage 1.</div>
|
|
</div>
|
|
<div class="comfy-node">
|
|
<div class="comfy-node-title">OVERLAY - FEEDBACK</div>
|
|
<div class="comfy-node-body">Cleaner mouth movement on fast turns.
|
|
Background retains 2K structure.
|
|
motion: 4/5
|
|
sync: 5/5
|
|
sharp: 4/5</div>
|
|
</div>
|
|
</div>
|
|
</figure>
|
|
</article>
|
|
|
|
<article class="timeline-item reverse">
|
|
<div class="timeline-copy">
|
|
<p class="eyebrow">In the agent</p>
|
|
<h3>One command turns the latest JSON into a review artifact.</h3>
|
|
<p><strong>/make-card</strong> finds the newest non-loop workflow JSON, extracts node parameters, writes the card, and appends the iteration log.</p>
|
|
</div>
|
|
<figure class="timeline-visual terminal">
|
|
<div class="mini-head">Command output</div>
|
|
<pre><span class="prompt">$</span> /make-card
|
|
Reading newest workflow JSON...
|
|
Writing <span class="path">_AI/card.png</span>
|
|
Appending <span class="path">_AI/iterations.md</span>
|
|
|
|
Card ready:
|
|
<span class="path">/JOBS/scene/ComfyUI-working-folder/_AI/card.png</span></pre>
|
|
</figure>
|
|
</article>
|
|
|
|
<article class="timeline-item" id="findings">
|
|
<div class="timeline-copy">
|
|
<p class="eyebrow">When evidence settles</p>
|
|
<h3>Promote patterns so they stop being rediscovered.</h3>
|
|
<p>When a knob behaves the same way across several runs, move the conclusion into the model's <strong>findings.md</strong>. The loop gets smarter because the docs shrink toward truth.</p>
|
|
</div>
|
|
<figure class="timeline-visual findings-box">
|
|
<div class="mini-head">LTX 2.3 findings snapshot</div>
|
|
<div class="finding-row">
|
|
<b>Scheduler</b>
|
|
<span><code>linear_quadratic</code> with 8 steps is the current locked path.</span>
|
|
</div>
|
|
<div class="finding-row">
|
|
<b>Sampler / CFG</b>
|
|
<span><code>euler</code> and <code>CFG 1.0</code> stay fixed while sweeping other knobs.</span>
|
|
</div>
|
|
<div class="finding-row">
|
|
<b>Resolution</b>
|
|
<span>2K is the recommended target for multi-segment work; 4K transitions currently dissolve.</span>
|
|
</div>
|
|
<div class="finding-row">
|
|
<b>Audio mode</b>
|
|
<span>Model-generated audio makes Phase 2 denoise visible as lip-sync drift.</span>
|
|
</div>
|
|
</figure>
|
|
</article>
|
|
</section>
|
|
|
|
<aside class="callout">
|
|
<p><strong>Reference layer:</strong> use <a href="./README.md">README.md</a> for the overview, <a href="./CONVENTIONS.md">CONVENTIONS.md</a> for the shared contract, <a href="./CHEATSHEET.md">CHEATSHEET.md</a> during a live session, and the per-module READMEs — e.g. <a href="./LTX-2.3/base-1step/README.md">LTX-2.3/base-1step/README.md</a> and <a href="./LTX-2.3/audio-lipsync/README.md">LTX-2.3/audio-lipsync/README.md</a>.</p>
|
|
</aside>
|
|
</main>
|
|
</body>
|
|
</html>
|