Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,49 @@ The format follows [Keep a Changelog](https://keepachangelog.com/1.1.0/) and thi
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — with the caveat
that the public API is not frozen until `1.0.0`. Pin an exact version.

## [0.1.1]

A patch over `0.1.0`. Every package is released together at the new version, including
the ones `0.1.0` did not break, so that one version number still describes one tested
set.

### Fixed

- **`lowest_landed_cost` could choose a container its own rate card cannot price.** When
one container billed lighter than another but its rate table ran out before the
shipment's billed weight, the search preferred it — returning the one packing you
cannot actually buy over a priced alternative. Every engine now compares candidates by
the money the rate table charges rather than by billed weight, which also fixes the
case this objective exists for: a bracket step or a minimum charge can make the
cheaper shipment the heavier one. If no container on offer can price the load, the
request is refused with a message naming the container, its billed weight and the last
bracket, in all four languages — previously two of them returned a result carrying a
sentinel cost, and two aborted requests that had a shippable answer. `RateTable` gains
a non-throwing `charge_minor_or_none` / `chargeMinorOrNull`; the throwing form is
unchanged. No request or result field changed.

- **`@packvium/engine@0.1.0` could not be imported.** The published tarball was missing
a runtime module that the fallback engine imports, so the first `import` of the package
threw `ERR_MODULE_NOT_FOUND`. npm versions are immutable, which is why the fix has to
arrive as a new version rather than a re-upload. Package assembly now dry-packs the
tarball and resolves every relative import in the real published inventory, so a
missing runtime file fails the release build instead of the consumer's first import.
Only the Node package was affected; the Python, PHP and Rust `0.1.0` releases install
and run correctly.

### Added

- **Commercial and control-plane API.** Three deterministic functions over one canonical
JSON document: `quote` returns a landed cost together with the tariff version that
produced it, `evaluate_policy` returns an eligibility decision together with the rule id
and version that decided it, and `catalog_version_info` returns the metadata of one
pinned catalog version. Exported as `packvium.commerce` (Python), `Packvium\Commerce\`
(PHP), `packvium_core::commerce` (Rust, plus three C ABI entry points) and `commerce`
on `@packvium/engine` and `@packvium/browser`. Prices are exact integers in minor
currency units and every inexact division rounds up, so a quote is reproducible rather
than approximately equal. No packing-request or packing-result field changed. Each
package ships a runnable `commerce` example; the contract is in `docs/COMMERCE-API.md`.

## [0.1.0]

First release.
Expand Down
17 changes: 17 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# What the source distribution carries beyond the importable package.
#
# setuptools builds an sdist from the declared packages plus a short list of standard
# metadata files, and silently drops everything else -- which left `pip download
# packvium` giving you the library and nothing to read. Every sibling port already ships
# both: the Rust crate carries its examples to crates.io, and the PHP and npm packages
# carry theirs. There is no reason Python should be the one ecosystem where you have to
# find the repository to see a worked example.
graft examples
graft tests

# `graft` is recursive and takes everything it finds, including whatever bytecode the
# last local test run left behind. Compiled caches are host- and interpreter-specific
# and have no business in a published artifact.
global-exclude __pycache__
global-exclude *.py[cod]
global-exclude .DS_Store
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Deterministic 3D cartonization and rectangular bin packing. Pure Python, **no runtime
dependencies**, exact integer geometry.

> **Version 0.1.0 — early release.** The public API is not frozen; pin an exact version.
> **Version 0.1.1 — early release.** The public API is not frozen; pin an exact version.
> Read [docs/GUARANTEES.md](docs/GUARANTEES.md) before relying on a result.

```bash
Expand Down Expand Up @@ -40,6 +40,22 @@ echo '{"items":[{"id":"box","quantity":8,"dimensions":{"length":"50","width":"50
| python -m packvium
```

## Examples

Runnable, in [`examples/`](examples). Each one is a single file you can read top to bottom
and execute without a project around it.

| File | What it shows |
| --- | --- |
| [`basic.py`](examples/basic.py) | The smallest useful call: items in, placements out. |
| [`constraints.py`](examples/constraints.py) | Upright-only, floor-only, non-stackable, top-load limits, and tags that keep two items out of the same box — plus how to read the reason an item was refused. |
| [`nested.py`](examples/nested.py) | Units into cartons, cartons onto a pallet, in one call. |
| [`commerce.py`](examples/commerce.py) | Rate a shipment, apply an eligibility rule, and pin a catalog version. |

```bash
python3 examples/constraints.py
```

## What it does

- **Exact arithmetic.** Length is measured in ticks of 1/16000 mm and weight in 1/8 µg.
Expand Down
Loading
Loading