# LinenBalance input and output reference LinenBalance reconstructs integer item counts from explicit movements. It does not connect to a laundry system, infer wash yield, attribute losses, generate invoices, or identify missing transactions. The included examples are synthetic. Run `python3 product.py samples/valid.json output-001`, or import `product` and call `run(payload)` or `bundle(payload)`. Python 3.12 or later needs only its standard library. The browser uses the same engine in a dedicated worker. Customer input is not sent to a server or language model. ## JSON input The root object contains `openings`, `movements` and an optional `policy`. `samples/valid.json` is the complete example: one tracked account opens at 100, dispatches 35 and receives 20, ending at 85. `samples/unknown.json` lacks an opening observation; `samples/invalid.json` contains an invalid movement. Each opening row has `account`, `sku`, `unit` (nonempty strings), and `quantity` (a nonnegative integer). The key is the exact account/SKU/unit combination. Repeated identical openings are idempotent; conflicting openings fail. Openings must describe holdings at the start of the selected period. That is an input assumption: this program cannot prove when a source count was observed. Each ordinary movement has `movement_id`, `type`, `timestamp`, `source`, `destination`, `sku`, `unit`, and positive integer `quantity`. Types are `dispatch`, `receipt`, `disposal`, `correction`, and `adjustment`. Direction always comes from the declared source and destination, including corrections. The source and destination must differ. A disposal with no JSON destination uses the explicit `__DISPOSED__` sink. CSV rows must name a destination. A `reversal` has only `movement_id`, `type`, `timestamp`, and `reverses`, which names the exact original movement. It cannot carry its own item, quantity or direction. An unknown reference, a second reversal, or a reversal earlier than its original remains unresolved and produces UNKNOWN. It never guesses a match. Replaying an identical movement ID and payload counts it once. Reusing an ID with a different payload fails, including changes in metadata. Movement order in the input does not determine posting order: UTC timestamps and IDs do. `policy.period` is an optional object containing `start` and `end`; the interval includes its start and excludes its end. Every timestamp must carry an explicit UTC offset or `Z`. This distinguishes repeated local hours at a daylight-saving transition. Naive local times are rejected. `policy.timezone` is a displayed business-timezone label; explicit offsets govern the actual arithmetic. The engine does not invent offsets from that label. Without a period, it includes the observed movement range. Empty data remain UNKNOWN. `policy.tracked_accounts` optionally names the accounts whose absolute balances must be known for an overall PASS. Without that explicit list, all observed accounts except the disposal sink are tracked. External counterparties may be excluded explicitly, but their missing opening/closing values still display UNKNOWN. With a tracked account, a missing opening is never silently treated as zero. Units are independent exact labels: pieces and kilograms never net against each other. Fractional quantities are outside this count-based edition. ## CSV and file input `files_to_payload(files)` takes a dictionary of basenames, each mapped to `{"encoding":"utf8","content":"..."}` or strict base64 content. No file is opened by this API. Supported choices are: - `opening.csv` and `movements.csv`, with optional `policy.json`; - exactly `input.json`, containing the JSON object described above. Opening headers are `account,sku,unit,quantity`. Movement headers are `movement_id,type,timestamp,source,destination,sku,unit,quantity`, with an additional `reverses` column when needed. A reversal row leaves the ordinary movement fields empty. Standard quoted CSV values are supported. Duplicate, empty or padded headers, ragged rows and invalid integer counts fail. CSV identifier fields are trimmed; JSON identifier strings are preserved exactly. The actual compatible files are in `samples/file-input/`. The offline batch runner additionally supports explicit column mapping profiles, so an export's headers can be renamed consistently without guessing what they mean. ## Evidence package `run` returns PASS, FAIL or UNKNOWN, a summary, tables, findings and provenance. `bundle` refuses invalid input and returns a deterministic ZIP for accepted computations, including computations with explicitly unknown balances. - `accounts.csv`: observed opening, incoming, outgoing, net and closing values; - `unresolved.csv`: unresolvable movement references; - `movement-lineage.csv`: exact event, UTC time, source/destination and posting; - `opening-close.json` and `policy.json`: resulting balances and applied policy; - `report.json`, `input.json`, `manifest.json` and hashes: reproducibility evidence; - `drilldown.html`: an escaped, portable count table. Every internal transfer posts an equal negative and positive integer entry. For a known opening, closing equals opening plus incoming minus outgoing. Negative closings are preserved with a warning; they can expose incomplete records but cannot establish physical loss or misconduct. Text that could be interpreted as a spreadsheet formula is quoted in CSV exports. Numeric cells retain their numeric values. Check the JSON when exact original text matters. The command exits 0 for PASS, 2 for FAIL and 3 for UNKNOWN. Files are written atomically. A failed rerun clears a previous result ZIP in the requested output directory; use a new directory to retain an earlier result. `run_json` rejects duplicate keys, nonfinite numbers and invalid JSON. Limits are 200,000 rows per input list, 4,096 characters per identifier, absolute quantity at most 10^12, 8 MiB per encoded uploaded file, 32 MiB per JSON payload, and nesting depth 16. `bash SMOKE.sh` runs the unit tests and actual valid/invalid/unknown CLI paths. `test_independent.py` adds source-order and time-boundary, missing-observation, CSV ambiguity, JSON, formula, reversal and filesystem adversaries. The test fixtures establish supported computation behavior, not customer demand, upstream export compatibility or a professional conclusion. The portable HTML report uses the canonical USTA styles and requested Satoshi stack. Offline font requests are disabled; the system fallback renders without a network request. No font is bundled or redistributed.