Commit Graph
32 Commits
Author SHA1 Message Date
tack c223d22981 feat(cli): --json machine-readable output mode 2026-04-23 15:53:07 +08:00
tack 6825d8520a feat(cli): validate entrypoint with exit codes + human output 2026-04-23 15:51:37 +08:00
tack 13254ea334 refactor(script_loader): use validate() for Layer 1 + Layer 2 safety net 2026-04-23 15:47:06 +08:00
tack 5a1feaf777 feat(validator): R5 page_template vs explicit dimensions 2026-04-23 15:41:00 +08:00
tack 7a14398a16 feat(validator): R4 panel width fits page 2026-04-23 15:39:56 +08:00
tack 6cd6e4c788 feat(validator): R3 vertical_stack layout fits page 2026-04-23 15:39:07 +08:00
tack 820d5eaece feat(validator): R2 panel_index continuity 2026-04-23 15:38:12 +08:00
tack d2abcdf514 refactor(validator): R1 use accumulate-all for consistency with R2-R5
Code review flagged that R1's early-exit (chosen in 1793f8d to satisfy
a len(errs)==1 assertion) would diverge from Tasks 3-6 which use
accumulate-all. Retrofit R1 + relax the test to use any()/next() so a
user fixes all continuity gaps in one validate pass. Also deepcopy the
page template in the fixture helper to avoid shared-ref leaks in later
rule tests.
2026-04-23 15:34:38 +08:00
tack 1793f8d957 feat(validator): R1 page_index continuity 2026-04-23 15:28:44 +08:00
tack 24122a189d feat(validator): scaffold CheckError + collect_errors for Layer 2 2026-04-23 15:22:36 +08:00
tackandClaude Opus 4.7 d9e241ad2e docs: M2 implementation plan (15 tasks, TDD per rule)
Plan derived from M2 spec — breaks validator Layer 2, CLI, schema export,
skill pack, and examples into 15 bite-sized tasks. Each task lists exact
file paths, test code, implementation code, shell commands, and commit
message so a fresh engineer can execute task-by-task without context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:15:17 +08:00
tackandClaude Opus 4.7 5127cf36bb docs: M2 spec — validation layer 2 + skill delivery pack
Design for M2 milestone covering:
- Layer 2 semantic validator (5 rules, M1 feature subset)
- Standalone CLI with human + --json output modes
- schema.json as single source of truth (exported from core/schema.py)
- Skill pack for AI-as-storyboarder workflow: SKILL.md, PROMPT_TEMPLATE,
  README, and 5 examples each with screenplay.md + output.json
- Canvas-size defaults (1080x1920) to anchor AI composition judgments

Layer 3 pre-generation checks, shape_group/polygon rules, and non-custom
page_template dimension tables are explicitly deferred to later milestones.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:06:00 +08:00
tackandClaude Opus 4.7 1aef0f2ced refactor: M1 polish pass (I2, I3, I5, I7)
Four minor improvements flagged in the M1 holistic review:

- I7: Extract core/image_ops.py with arr_to_pil / pil_to_arr / hex_to_rgb.
  Removes the three duplicated copies scattered across compositor,
  batch_generator, and page_composer. Sets up cleaner reuse for M2/M3
  when validator and polygon mask code need the same helpers.

- I5: Move `import torch` out of module top-level in both node files,
  into the methods that actually use it. Keeps the ComfyUI node scan
  cheap — torch is the heaviest dependency by far.

- I3: Rename the `retries` widget to `max_attempts` (default 3, min 1).
  The old name was misleading: retries=2 meant 3 total attempts.
  Log lines now read "attempt N/M" for clarity.

- I2: Add manifest_version: 1 to cache manifests. manifest_matches()
  now treats missing/mismatched versions as stale, so a future hash
  schema change can safely invalidate old caches by bumping the
  constant in core/cache_manager.py.

Tests updated to new kwargs, plus 2 new regression tests covering the
manifest-version behaviour. 74/74 pass, ruff clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:43:00 +08:00
tackandClaude Opus 4.7 c810408f9b feat(nodes): add ComicSamplerOverride for runtime sampler tweaks
Optional node that plugs between ComicScriptLoader and ComicBatchGenerator
when the user wants to experiment with cfg / steps / sampler without
editing the JSON. Any widget left at its sentinel value ((keep), 0, 0.0,
-1.0) is ignored; non-sentinel widgets overwrite every panel's sampler,
including panels that had per-panel sampler_override in the JSON.

Workflow stays JSON-authoritative by default: don't insert the node and
the JSON is the single source of truth (I4 / spec §14). Insert it only
for ad-hoc experimentation.

Panels are rebuilt via dataclasses.replace — the input SolvedScript is
never mutated, keeping C1's no-mutation invariant. Cache hashing picks
up the new sampler values automatically.

Registered as "Comic Sampler Override (experimental)" in NODE_CLASS_MAPPINGS.
5 tests cover: passthrough, single-key override, no-mutation, override
winning over per-panel sampler_override, and mixed partial override.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:35:06 +08:00
tackandClaude Opus 4.7 ad9dda654f refactor(batch_generator): drop redundant sampler widgets (I4)
Schema requires default_sampler at book level to contain all 5 keys
(sampler_name, scheduler, steps, cfg, denoise), and the normalizer
always populates panel.sampler from it. The node-level widgets were
dead code — the merge `{**widget, **panel.sampler}` always collapsed
to panel.sampler.

Remove the 5 sampler widgets from INPUT_TYPES so the node stays faithful
to the design principle "schema is the single source of truth"
(spec §14). JSON's default_sampler + per-panel sampler_override are now
the only way to configure sampler params.

positive_suffix / negative_suffix widgets remain — they are explicit
run-time overrides, not duplicates of JSON config.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:25:54 +08:00
tackandClaude Opus 4.7 08ab053790 fix(batch_generator): stop mutating input panels & persist skip placeholder
C1: generate() baked widget defaults + prompt suffixes into the caller's
SolvedPanel, breaking cache invalidation on widget edits and leaking
mutated prompts into the pass-through comic_script output. Replace the
in-place mutation with dataclasses.replace into a local run_panel used
for hashing and sampler invocation; the input script is never touched.

C2: retry_then_skip exhausted retries returned a red-X placeholder but
wrote nothing to disk, so the next run re-sampled the failing panel
instead of staying skipped. Persist placeholder PNG + manifest with
{"status": "skipped"} so manifest_matches keeps the panel skipped.

Also assert sampler-returned shape == (h, w, 3) and add a defensive
shape check in page_composer before cropping.

Regression tests added: no-mutation, skip persistence across runs, and
shape-mismatch halt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:08:55 +08:00
tackandClaude Sonnet 4.6 4738a10321 docs: document M1 nodes + restore NODE_CLASS_MAPPINGS export
Overwrite README.md with full M1 documentation (nodes table, install,
test, limitations). Restore NODE_CLASS_MAPPINGS / NODE_DISPLAY_NAME_MAPPINGS
in __init__.py now that all three node modules exist; import order fixed
for ruff I001.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:52:06 +08:00
tackandClaude Sonnet 4.6 1e4ccca032 test: add E2E integration test + example ComfyUI workflow
Add test_integration_e2e.py that exercises the full loader → generator
→ composer pipeline with GreyBackend, asserting 2 pages, 4 panels, and
cache-hit behaviour on second run (PNG round-trip tolerance atol=1/255).

Add examples/workflows/m1_basic_vertical_stack.json as a reference
ComfyUI workflow JSON wiring CheckpointLoaderSimple → ComicScriptLoader
→ ComicBatchGenerator → ComicPageComposer → SaveImage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:48:28 +08:00
tackandClaude Sonnet 4.6 9d3a587cf6 style(core,nodes,tests): apply ruff import sort & modern type annotations
Auto-fix all I001 (unsorted imports), UP007 (Optional → X | None),
UP035 (typing.Iterable → collections.abc), B905 (zip strict=),
and F401 (unused imports) violations across core/, nodes/, and tests/.
No behaviour change; 64 tests still pass after fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:48:15 +08:00
tackandClaude Sonnet 4.6 c97190fe2e feat(nodes): add ComicPageComposer (rect + bbox metadata)
Assembles per-panel IMAGE tensors onto full page canvases via compose_page,
emits panel_bboxes_json metadata, and passes the original panel stack through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:41:56 +08:00
tackandClaude Sonnet 4.6 33c7eb5098 feat(nodes): add ComicBatchGenerator with resume + retry
Implements panel-level cache-skip (manifest hash), per-panel retry loop,
halt vs retry_then_skip failure modes, and white-padding before stacking
mixed-height panels into a single (N,H,W,3) tensor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:36:45 +08:00
tackandClaude Sonnet 4.6 1ca2e5e5d7 feat(nodes): add ComicScriptLoader (file/path/inline modes)
Implements the ComfyUI input node that loads, validates, and normalizes
comic script JSON via three modes (file, path, inline), plus conftest.py
with a folder_paths stub for CI and 6 TDD tests covering all modes and
error handling.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:29:59 +08:00
tackandClaude Sonnet 4.6 0c1ed9b310 feat(core): add rect-only page compositor with border
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:25:28 +08:00
tack 0fd29a4665 feat(core): add backend-agnostic sampler runner 2026-04-23 12:22:42 +08:00
tack 3943226e07 feat(core): add panel-hash cache manager for resume
SHA256-based panel fingerprinting over content fields (excludes bbox_topleft),
with manifest read/write and stale-detection for skip-on-resume logic.
2026-04-23 12:18:50 +08:00
tackandClaude Sonnet 4.6 7b965a4ee6 feat(core): add script normalizer (defaults + layout + prompts + seeds)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:14:18 +08:00
tackandClaude Sonnet 4.6 a215e64af0 feat(core): add vertical_stack rect layout solver
Implements solve_vertical_stack() with left/center/right alignment,
gutter support, and LayoutError for overflow and oversized panels.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:08:50 +08:00
tackandClaude Sonnet 4.6 97079a66fe feat(core): add 4-layer prompt builder
Implements build_prompt_pair() joining style/character/page/scene layers
with suffix support; skips empty/whitespace/trailing-comma fragments.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:04:38 +08:00
tackandClaude Sonnet 4.6 36640fef93 feat(core): add schema validator with path-aware errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 12:00:03 +08:00
tackandClaude Sonnet 4.6 08c39dbe8c feat(core): add M1 JSON schema (rect-only) + fixtures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 11:55:29 +08:00
tack 26f860cc71 feat(core): scaffold package + SolvedScript/Page/Panel types 2026-04-23 11:48:59 +08:00
tack e76cd2bd3d docs: add design spec + M1 implementation plan 2026-04-23 11:43:42 +08:00