# LinenBalance: file and automation reference This technical reference describes actual local interfaces. It is not a claim of a hosted API, vendor connector or additional paid calculation. The free tool and the fixed-version kit use the same engine. ## Inputs - opening.csv + movements.csv + optional policy.json - input.json alone | File | Format | Sample columns | |---|---|---| | `movements.csv` | CSV | `movement_id`, `type`, `timestamp`, `source`, `destination`, `sku`, `unit`, `quantity`, `reverses` | | `opening.csv` | CSV | `account`, `sku`, `unit`, `quantity` | | `policy.json` | JSON | | The actual files in `samples/file-input/` are synthetic fixtures. Optional file schemas and every semantic constraint are in the [engine README](README.md). Exact JSON structure is in the product schema and README. A filename is an exact basename, never a disk path passed to the engine API. ## CLI and Python Run from an extracted trusted kit directory using Python 3.12 or newer. TileMosaic also requires the versions in `requirements.txt`. ```sh python3 product.py samples/valid.json output-001 ``` ```python import json from pathlib import Path import product payload = json.loads(Path("samples/valid.json").read_text()) report = product.run(payload) if report["status"] != "FAIL": Path("result-api.zip").write_bytes(product.bundle(payload)) print(report["status"]) ``` For real files, use the common `run_files.py` example: it encodes PNG/STDF bytes with base64, passes text as UTF-8, and calls `files_to_payload` before the same `run`/`bundle` functions. These are local Python functions, not HTTP endpoints. Call `run_json(text)` for strict JSON parsing; duplicate keys and nonfinite numbers are refused. ## Batch folders and exact column profile Each immediate subdirectory of `jobs/` is one independent engine payload. Copy all required files into that folder. Use `input.json` for a multi-period RoyaltyWaterfall history or an explicitly ordered multi-file TestLotReplay history; splitting those dependent histories into independent folders does not carry state. ```sh mkdir -p jobs/example cp samples/file-input/* jobs/example/ python3 batch.py jobs results-001 ``` A profile maps destination header to source header. This complete example corresponds to the sample CSV files with every header renamed to `export_...`; normal sample headers need no profile. ```json { "movements.csv": { "movement_id": "export_movement_id", "type": "export_type", "timestamp": "export_timestamp", "source": "export_source", "destination": "export_destination", "sku": "export_sku", "unit": "export_unit", "quantity": "export_quantity", "reverses": "export_reverses" }, "opening.csv": { "account": "export_account", "sku": "export_sku", "unit": "export_unit", "quantity": "export_quantity" } } ``` Save the profile as `columns.json` outside the job folder, then run `python3 batch.py jobs results-002 --profile columns.json`. For PNG/STDF/JSON-only inputs the profile is `{}` and can be omitted. Profiles rename columns only: no unit, currency, timestamp or value conversion. Destination order is significant for strict CSV readers. The outer runner deliberately projects only mapped columns; retain and review the original export. Missing/duplicate headers, ragged rows and nonunique mapped source columns fail. Engine-specific validation still runs after mapping. ## Result file schema observed by executable example Columns and JSON keys observed in the synthetic PASS fixture; variable recipient, source, pyramid and map filenames depend on input. Read README.md for UNKNOWN omissions and semantic rules. | ZIP member | CSV columns or observed JSON keys | |---|---| | `README.txt` | | | `accounts.csv` | `account`, `sku`, `unit`, `opening`, `incoming`, `outgoing`, `net`, `closing`, `closing_known`, `tracked` | | `drilldown.html` | | | `hashes.json` | `README.txt`, `accounts.csv`, `drilldown.html`, `input.json`, `movement-lineage.csv`, `opening-close.json`, `policy.json`, `report.json`, `styles.css`, `unresolved.csv` | | `input.json` | `movements`, `openings`, `policy` | | `manifest.json` | `engine`, `files`, `status` | | `movement-lineage.csv` | `movement_id`, `type`, `timestamp_utc`, `source`, `destination`, `sku`, `unit`, `quantity`, `reverses`, `in_period`, `posted` | | `opening-close.json` | `engine`, `lines`, `status` | | `policy.json` | `engine`, `period`, `timezone`, `tracked_accounts` | | `report.json` | `findings`, `provenance`, `status`, `summary`, `tables` | | `styles.css` | | | `unresolved.csv` | `movement_id`, `type`, `reverses`, `reason` | CSV text that could execute as a spreadsheet formula is neutralized; original JSON preserves exact text. Read report status and the relevant coverage/completeness fields before importing numeric rows. UNKNOWN is an unobserved result, not zero. PASS is computation under declared inputs and policies, not a professional conclusion. ## Supported handoffs - **Buyer-owned laundry export → LinenBalance** (CSV): Rename approved columns; preserve immutable movement IDs, offsets and count units. Supported local file boundary only; upstream export and downstream product compatibility require buyer validation. - **accounts.csv and movement-lineage.csv → Buyer-owned period review** (CSV/JSON): Import the count table as data and retain lineage beside it. No invoice or ERP write is performed. Supported local file boundary only; upstream export and downstream product compatibility require buyer validation. ## Scope boundaries - Integer item counts only; exact account/SKU/unit keys; explicit UTC-offset timestamps. - Missing opening counts remain UNKNOWN. The engine cannot identify omitted transactions or physical losses. - Reversal references must name the exact original movement; conflicting IDs fail. ## Replay evidence Engine SHA256: `df8af1d5ae5a4a22aab3a5e67d327f5b8285184c9bbf23dc09c6f57aace904f0`. The documentation builder ran the actual synthetic file set and reopened its result archive. This verifies the local format example, not customer file compatibility, deployment, demand or financial return. Same-version bytes can be compared in one pinned environment; Python/zlib or TileMosaic dependency upgrades can change archive bytes. See the [common automation reference](../integrations.md) for scheduling, CI and batch receipt semantics.