Phase 4 · Build: compose the bricks, then apply the signed change list
Produce the customer's repo: it depends on the bricks at their tags and holds only what is the
customer's. Build only from a signed change list. Back: dodil://erp/build.
Steps
- Already ran
initat Discover (HR)? Skip to step 2: that folder is the build. Otherwise run one command IN THE PROJECT FOLDER (your current working directory: the customer's repo; never/tmpor a scratch path, or the customer can't find what you built), naming the module(s); no DODIL login needed:
Nouvx --from git+https://git.dodil.io/dodil/erp-platform.git@v0.9.13 erp-compose init hruvx?python3 -m venv ~/.erp-compose && ~/.erp-compose/bin/pip install git+https://git.dodil.io/dodil/erp-platform.git@v0.9.13 && ~/.erp-compose/bin/erp-compose init hr. It reads this method'sreference.reposandbrick_entries, PINS each brick at its tag inrequirements.txt, installs them into.venv(erp-platform first), writescompose.yamlandtests/test_composition.py, and runserp-compose checkand the test. It must end withReady(else fix what it names); never hand-write these files;--read-copyto read bricks. A UK trading business?init --starter uk-wholesale(erp-platform >= 0.9.10) writesconfig/starter.calls.yaml(company, chart, VAT, maps, warehouse, bank, terms, price list; no products):erp-compose migrate --local,seed --local compose.yaml config/starter.calls.yaml(re-runnable),serve --local. A sample customer, product and 100 in stock is OPTIONAL (starters/uk-wholesale-sample, seed it second; skip it if the business has its own products). - Configure: apply the change list in order, by depth:
- depth 1: rows, through the bricks' own use cases (for HR the signed
config/hr.calls.yaml, replayed as is; never an INSERT into a brick's table, never an edit underbricks/). Then runerp-compose signoff verify --all: every signed process must say SIGNED.
- depth 1: rows, through the bricks' own use cases (for HR the signed
- Extend (depth 2): a new brick in the customer's org from
erp-platform/templates/brick-example/(BRICKS.md) providing the capability, added tocompose.yaml. A module no brick covers is a new brick in the same shape (modules/pattern.md§2), its logic generated fromERP_<MODULE>.md, with the story id in each use case's docstring. - Own (depth 3), ONLY for a change the signed BPMN draws:
erp-compose own <brick> --reason "<CR>". A wish the diagram does not show (e.g. "escalate to a director" where the brick sends it to HR) is NOT code in this build: record it under Change requests, say so, and take it throughdodil://erp/phase/change(propose, sign, then code). Lab, 2026-10-18: a builder editedowned/brick-hrfor a step it said "isn't in the diagrams"; the build no longer was the signed one. - The gate (erp-platform v0.8.2, its own step):
uvx --from git+https://git.dodil.io/dodil/erp-platform.git@v0.9.13 erp-compose plan compose.yamlREFUSES a module with no signed process (signoff/<module>/<process>.json), a pending change, or a BPMN that no longer matches what was signed; so doesmigrate. Never route around it:--unsigned "<reason>"is recorded insignoff/<module>.unsigned.jsonand the bench sees it. From v0.8initPINS the bricks in requirements.txt (nobricks/;--read-copyto read them); depth 3 iserp-compose own <brick> --reason "<CR>"(copies it toowned/, records the upstream tag). - Show it on localhost, no cloud:
erp-compose migrate --local compose.yaml, thenserve --local --clock +1d(SQLite, 127.0.0.1; settings are in force from tomorrow). Tick each change item built in Deviations.
What init writes, for reference (HR, in a folder named acme)
name: acme-hr
version: 0.1.0
tier: 1
bricks:
- { name: hr, brick: "brick_hr.application.use_cases:HR", version: 0.5.0 }
- { name: bp, brick: "brick_bp.application.use_cases:BP", version: 0.3.1, process_view: "none: master data only, no lifecycle to sign" }
Done when
-
erp-compose checkis clean andtests/test_composition.pypasses. - Every change item is built, and the regenerated process view matches the signed one.
- No brick clone differs from its tag except a declared fork.
-
erp-compose planpasses the gate with no--unsigned.
Next: dodil://erp/phase/test