Skip to content

Repository files navigation

DarkBatch

CI Python 3.11+ MIT license

Know whether every exposed roll fits your tanks, reels, and declared chemistry before you open the changing bag.

DarkBatch is an offline command-line planner for analog photographers processing several film rolls in one session. Give it your already-verified recipes, configured tanks, chemistry lots, and rolls. It performs an exact bounded search and either writes a complete batch plan or stops with measured shortage evidence and a repair you can act on.

VALID: Saturday five-roll session; rolls=5, tanks=3, chemistry_lots=2
PLANNED: 5 rolls -> 2 batches; reports=darkbatch-demo

The result is not a timer or a recipe database: it is a feasibility check for the whole session. Your manifest and reports stay on your machine, and the installed program has no runtime dependencies or network access.

Install

Python 3.11 or newer is required. Install the published v0.1.0 wheel directly from its GitHub Release:

python -m pip install https://github.com/KanadeK/darkbatch/releases/download/v0.1.0/darkbatch-0.1.0-py3-none-any.whl

Confirm the installed entry point:

darkbatch version
darkbatch 0.1.0

60-second quick start

Download the committed five-roll example, validate it without writing anything, then create the reports:

curl -LO https://raw.githubusercontent.com/KanadeK/darkbatch/v0.1.0/examples/saturday-session.json
darkbatch validate saturday-session.json
darkbatch plan saturday-session.json --out darkbatch-demo

darkbatch-demo contains exactly three files:

  • plan.json — stable machine-readable allocations, quantities, timing, and remaining chemistry;
  • batch-cards.md — printable bench cards with roll IDs and mix quantities;
  • timeline.svg — a standalone visual timeline for the sequential session.

The example's plan is real, not a canned result:

Batch Rolls Tank Declared chemistry Mix Nominal window
1 roll-004, roll-005 dual-600 color-lot-1 150 ml stock + 450 ml water 0–18 min
2 roll-001, roll-002, roll-003 wide-900 mono-lot-1 450 ml stock + 450 ml water 18–32 min

DarkBatch chose two batches—the fewest possible—then minimized total working solution and stock use. Lexical tie-breaking makes the same manifest produce the same plan.

Describe your own session

A manifest is UTF-8 JSON with five required top-level fields. Recipe values are deliberately user-owned: copy only values you have checked against the current chemistry and tank manufacturers' instructions and safety data.

{
  "project": "One-roll check",
  "recipes": [
    {
      "id": "my-verified-recipe",
      "stock_parts": 1,
      "water_parts": 1,
      "minimum_stock_ml_per_roll": 100,
      "process_minutes": 12
    }
  ],
  "tanks": [
    {
      "id": "my-300ml-tank",
      "working_volume_ml": 300,
      "reel_capacity": 1,
      "formats": ["135"]
    }
  ],
  "chemistry": [
    {
      "id": "opened-bottle-a",
      "recipe": "my-verified-recipe",
      "stock_ml": 200,
      "roll_capacity": 1
    }
  ],
  "rolls": [
    {
      "id": "roll-001",
      "format": "135",
      "recipe": "my-verified-recipe",
      "reel_units": 1
    }
  ]
}

For each possible tank load, required stock is the greater of:

ceil(working volume × stock parts / total parts)
minimum stock per roll × number of rolls

Both the declared stock_ml and roll_capacity are consumed. Rolls can share a batch only when their recipe IDs match exactly, every format is supported by the tank profile, and total reel_units fit its capacity. Tanks and reels are reusable because v0.1 models one sequential session.

The full field contract and ranking rules are in the v0.1 specification.

Failure that tells you what to fix

The shortage fixture is structurally valid but cannot cover both rolls:

darkbatch plan examples/insufficient-chemistry.json --out should-not-exist
[CHEMISTRY_STOCK_SHORTAGE] Recipe 'recipe-a' lacks enough stock concentrate. Evidence: required=300ml, available=250ml, shortfall=50ml Repair: Provide at least the stated additional stock or use valid lower-volume tanks.

The command exits 1 and does not create should-not-exist. Invalid JSON, missing fields, broken references, unreadable inputs, and an already-existing output path exit 2 with a stable code and a repair action.

Exit Meaning
0 The manifest is valid; plan also found and wrote a complete allocation.
1 The manifest is valid, but the declared physical resources cannot cover every roll.
2 The input, path, or command is invalid and must be repaired before planning.

Known limits and safety boundary

  • DarkBatch does not verify recipe truth, developer/film compatibility, chemical safety, temperature, agitation, wash/fix stages, or the physical truth of a tank profile.
  • It never recommends a film/developer combination and never controls darkroom hardware.
  • v0.1 models one sequential session, not simultaneous processors or replenishment.
  • Exact search is intentionally limited to 16 rolls, 8 tank profiles, and 16 chemistry lots.
  • A feasible mathematical allocation is not a guarantee of chemical safety, image quality, or correct physical loading. Current manufacturer instructions remain authoritative.

Troubleshooting

Message or symptom What to do
darkbatch is not found Run python -m pip show darkbatch, then ensure that Python's scripts directory is on PATH. You can also run python -m darkbatch version.
[INPUT_IO] Check the manifest path and read permissions. Relative paths are resolved from the current directory.
[INVALID_JSON], [MISSING_FIELD], or [UNKNOWN_FIELD] Fix the named JSON location. Start from a file in examples/ if needed.
[OUTPUT_EXISTS] Choose a new --out directory or move the existing owner data yourself. DarkBatch never overwrites it.
A chemistry or tank diagnostic exits 1 Read its Evidence and Repair text; revise only the real resource declaration or session, then rerun.

Development

The repository uses uv for a locked development environment:

uv sync --locked --dev
uv run --locked python scripts/check.py

That single gate is also CI's final command. It verifies formatting, lint, strict types, branch coverage, all committed examples, local Markdown links, wheel and sdist creation, clean wheel installation, and a real run through the installed darkbatch entry point.

See CONTRIBUTING.md, the changelog, and the project-selection evidence. Security reports are handled as described in SECURITY.md.

DarkBatch is released under the MIT License.

About

Exact offline batch planning for analog film development sessions

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages