Build an installable, deterministic CLI that converts structured comic-page geometry into an ordered dialogue handoff and annotated evidence. It must support LTR and RTL pages, allow explicit ordering constraints, reject invalid or ambiguous inputs, and produce useful artifacts without network access or runtime dependencies.
- As a letterer, I can number balloons consistently and see where declared geometry is under-specified.
- As a translator, I can receive an ordered CSV/Markdown script with stable balloon IDs and source text.
- As a maintainer, I can run the same page through CI and receive deterministic JSON and exit codes.
- Python 3.11–3.13 support.
- Standard-library runtime:
argparse,csv,dataclasses,html,json, andpathlib. - Setuptools build backend declared through
pyproject.toml. - Development: uv lock/sync, pytest + pytest-cov, Ruff, mypy, build, and pip-audit.
- GitHub Actions on Ubuntu with explicit Python setup.
Each JSON file contains:
schema_version: exactly"1".page:id, positivewidth/height, andreading_direction(ltrorrtl).panels[]: uniqueid, positive rectangularbox, optionalafter[]panel IDs.balloons[]: uniqueid, existingpanel_id, positive rectangularbox,speaker,text, optionalafter[]balloon IDs in the same panel, and optionaltailpoint.
Unknown fields are rejected in v0.1 so misspellings cannot silently change output. Coordinates are finite numbers in page units.
check INPUT [--json] validates and analyzes without writing artifacts.
compile INPUT --out DIRECTORY writes:
report.json: schema version, page metadata, ordered entries, and structured diagnostics.script.md: human-readable dialogue in reading order.localization.csv: stable IDs, order, speaker, source text, and a blank translation column.preview.svg: panels, balloons, tails, and order labels.index.html: a self-contained report embedding the SVG and tables.
Exit codes: 0 clean or warnings only; 1 analysis contains blocking errors; 2 invalid JSON/schema/CLI usage or an I/O failure. compile writes nothing when blocking diagnostics exist.
Diagnostics expose code, severity, message, and related IDs. Codes and structured fields are stable; prose may improve between compatible versions.
- A deterministic visual key groups non-overlapping rectangles top-to-bottom, then orders members of the same vertical band left-to-right or right-to-left.
afterconstraints are hard directed edges and take precedence over the visual key during stable topological sorting.- A cycle is blocking.
- Rectangles whose interiors overlap are geometrically ambiguous unless an explicit ordering path relates them; the overlap remains visible as a warning even when order is explicit.
- Panels are ordered first; balloons are ordered within their declared panel. A balloon may not constrain a balloon in another panel.
src/balloon_order/
model.py validated dataclasses and diagnostics
loader.py JSON boundary parsing and schema validation
geometry.py rectangle/segment relationships
ordering.py visual keys and stable topological order
analyze.py page-level orchestration and diagnostics
exporters.py JSON/Markdown/CSV/SVG/HTML rendering
cli.py argument parsing, exit codes, and file writes
tests/ unit, integration, CLI, and determinism tests
examples/ LTR, RTL, and broken page fixtures
docs/ research, spec, decisions, demo assets, repair guide
scripts/verify.py complete local release gate
tasks/ implementation plan and checklist
Typed dataclasses carry validated internal state; direct functions express each transformation:
def order_boxes(items: tuple[OrderableBox, ...], direction: Direction) -> tuple[str, ...]:
visual_rank = build_visual_rank(items, direction)
return stable_topological_order(items, visual_rank)Use descriptive names, frozen dataclasses, explicit return types, and no broad exception handling in the core. CLI converts known boundary failures to exit code 2; unexpected errors fail with their traceback during development.
- Unit tests: box containment/intersection, segment crossings, row/direction ordering, hard constraints, and cycles.
- Analysis tests: outside geometry, overlaps with and without constraints, tail crossings, and cross-panel references.
- Export tests: exact ordered rows, escaped user text, deterministic bytes, and required SVG/HTML structure.
- CLI integration: clean compile returns
0; broken page returns1and creates no output; invalid schema returns2. - Package smoke: install the built wheel in a clean temporary virtual environment and compile the RTL example.
- Coverage floor: 90% for
src/balloon_order.
Bootstrap: uv sync --extra dev --python 3.12
Focused test: uv run pytest tests/test_ordering.py -q
Full test: uv run pytest -q
Coverage: uv run pytest --cov=balloon_order --cov-report=term-missing --cov-fail-under=90
Lint: uv run ruff check .
Format: uv run ruff format --check .
Types: uv run mypy src
Build: uv build
Demo: uv run balloon-order compile examples/rtl-page.json --out build/demo
Release gate: uv run python scripts/verify.py
- Always: validate at load, keep output deterministic, escape content in SVG/HTML/Markdown/CSV, test behavior before implementation, update docs with public changes.
- Ask first: add runtime dependencies, broaden geometry beyond rectangles, add network access, or change exit/diagnostic semantics.
- Never: execute input, fetch referenced URLs, hide diagnostics, emit artifacts after a blocking error, commit secrets, or claim automatic understanding of page images.
- LTR and RTL examples compile into all five artifacts with the expected order.
- A broken example reports at least an ambiguity/outside/tail issue, exits
1, and writes no compile directory. - Explicit constraints resolve order ambiguity; cyclic constraints fail.
- Tests, 90% coverage, lint, format, types, build, audit, wheel smoke, and secret scan pass.
- Git history contains only the configured KanadeK author/committer and no co-author trailers.
- Public GitHub repository, green CI, annotated
v0.1.0tag, published Release assets, and online contributor verification exist before notification.
No unresolved question blocks v0.1.0. Multi-page spreads, polygon geometry, and editor importers are explicitly deferred.