A pack inside a pack¶
Asked by Scott, 2026-10-13: "I want this to be extremely robust and ensure scalable complexity with pack in pack scenarios, different styles of routings, different OPC organizational structures."
Routings and OPC organisation are answered: they are fields in the shape file
(format 2) and objects in the plant model, so a branching routing or a plant
whose tags live under channel/device folders is data, not a code change.
See skills/plant-from-your-mes/FORMAT.md and
docs/operate/plant-from-your-mes.md.
Pack-in-pack is the third one, and it is a question rather than a feature. This page answers it in one screen.
What "a pack inside a pack" could mean¶
Three different things get called that, and they have three different answers.
- A plant with areas and cells inside it — one site, several areas, cells under them, machines under those. A bottling hall and a packing hall under one roof, one dashboard, one shift calendar.
- Several plants that roll up — two factories, each with its own dashboard, its own shifts, its own database, reporting to one place.
- A pack that includes another pack as a part — a vendor ships
filler-line-v3as a folder, and a site pack lists it the way a BOM lists a sub-assembly.
What already works¶
(1) is done, today, with no nesting at all. A pack's
masterdata/equipment.json is the ISA-95 hierarchy as rows: every node has a
level (enterprise, site, area, work_center, work_unit) and a
parent. The tree is as deep as the rows say. The grouped reference shape in
this release is exactly that case — two areas, four cells, six machines — and it
comes out of one shape file, into one pack, onto one dashboard:
fsmes shape plant skills/plant-from-your-mes/example/plant-shape-grouped.toml --out ./acme
OPC organisation is separate from it and nests independently: tag_map.json
gives each machine a group, the folders above its own object, so two machines
can share one device node while sitting in different cells. A plant's address
space and a plant's org chart are not the same tree, and in brownfield sites
they routinely disagree.
(2) is the fleet, not a pack. Decision
0021 gives each plant its own
database; fsmes fleet runs several packs side by side and the console observes
them. Two factories are two packs and two ports, which is what a plant engineer
expects when one site's database goes down and the other keeps running.
(3) does not exist, and nothing in this release needs it.
What would force real nesting¶
Only one thing: a part of the plant that needs its own copy of something a
pack holds exactly one of. Concretely — its own time zone, its own shift
calendar, its own enabled module set, its own database, its own serving port, or
its own [words]. A hall in a different country is the honest example. Another
is a contract line that must stop and start without touching the rest of the
site.
Everything short of that — more areas, deeper cells, more routings, stranger tag folders, forty stations instead of six — is more rows in files a pack already has, and this release carries a 40-station, five-area, three-routing shape through to a running plant to show it.
Recommendation¶
Do not nest packs. Keep decision 0022 as it stands: a pack is one folder. Answer the three readings this way:
- Inside one plant, go deeper in
equipment.json. No format change, no new concept, andfsmes pack checkalready validates that every node's parent exists. - Across plants, use the fleet. If roll-up reporting is wanted later, that is a console feature reading several plants' APIs — not a pack that contains another pack.
- For a vendor-shipped line, the thing to add when somebody actually asks is
an include at build time, not nesting at run time:
fsmes pack composereading two folders and writing one. The pack the plant runs stays one folder, so nothing downstream —pack check,pack apply, the fleet, the console — learns a new shape.
The cost of being wrong here is small and the cost of being early is not. A pack
that can contain a pack doubles the number of states every reader of a pack has
to handle, forever, and fsmes pack check's whole value is that it can read a
pack with no database and no network and say "usable". Nesting is a feature with
one customer request and no customer; the hierarchy inside one pack has two
reference shapes and a test.
What is left open for it on purpose¶
The plant model keeps areas as its own objects with a parent of their own
(src/fsmes/shape/model.py), and the shape file's [hierarchy] table carries a
parent per area. Both are unused today — every area the converter writes sits
straight under the site — and both are there so that an area under an area, or
later a pack composed of two, needs no change to the shape file a customer has
already written on their own MES box.