Instructions for agents working on this brick
Built from the inventory module spec (erp-method modules/inventory, version 3, signed 2026-10-22). Read erp-platform's
BRICKS.md first: the rules and why each one exists. A process change goes through erp-compose change propose, the customer's
new signature, then the code.
Where a change goes
| You are changing... | It goes in |
|---|---|
| a business rule on values, valuation, locations, removal | domain/ (plain Python) and its test |
| the move engine (claims, valuation, tracking) | application/ledger.py |
| who may do something, which rows | the use case (permission= or common.need_read), never a role's name |
| a use case for people and agents | a function in application/<part>.py with @INV.use_case, imported in use_cases.py |
| how another module is reached | infrastructure/seams.py only (spec routes, never their tables) |
| a column or table | infrastructure/tables.py, then python scripts/gen_schema.py and a new migrations/NNNNN_<name>/ |
| an AI step | infrastructure/ai_steps.py and the use case that calls ask() |
The rules that must not be undone
- Stock is a ledger.
inv_moveis never updated or deleted; a mistake is a reversing move that names the original. On hand is derived from moves (Repository.stock); no quantity is stored.inv_valuation,inv_claim,inv_number_series,inv_reservationare append-only too, written with a PLAIN INSERT: a key another writer took is a lost race (ClaimLost). - Plan from reads, write at the end (
application/unit.py): DataK3 has no read-your-writes in a transaction. Claims are taken first (flush_races) and before any neighbour is told; a lost attempt is compensated and re-run on a fresh read. - Every quantity is in the product's base unit, exact (
Fraction); a conversion that does not fit four places is refused, never rounded. Money isround_half_uponce. - The sales order hears of a delivery only from here; a receipt is recorded only by purchasing (
scan_deliveryasks it to; purchasing posts each line back throughPOST /receipts). Nothing writesgl_,pur_,so_orprod_tables. - Cost and value are projected out for callers without
inv:valuation:read; a caller withoutinv:stock:readgets a 404. - Approvers are compared by email AND sign-in subject (
unit.identities). - 'Today' is
infrastructure/business_time.today()(the one business_timezone), neverdate.today(). - AI steps only suggest; no model is called in tests.