Skip to content

Direction, and the tree it is measured from

shipped 1.0.0

pull reads into the tree. push writes out of it. The environment argument names which site.

That sentence is the whole model, and The tree is the page that sets it up. This page is about what follows: the movements that are bulk and therefore downward only, the edges that skip the tree entirely and why the guard reads an effect rather than a command name.

The three edges that skip the tree

Most of what cwp does passes through the hub. Three things do not, and downward is the word for those three.

CommandEdgeDirection
cwp db pullsite → site — an environment’s database into the local containerdownward only
cwp media pullsite → site — an environment’s media files into the local containerdownward only
cwp fetchsite → disk — third-party themes and plugins, gitignoreddownward only
cwp dblocal only — snapshots of the container’s databaseneither

cwp pull is not in that table. It reads the tree, and the tree passes through the hub by definition. The database and the media are the first two rows, and they are different commands for that reason.

Every arc that skips the tree has one arrowhead and it points at this machine. The bulk rule is those arrowheads, drawn rather than asserted. The converse is the claim the whole tool rests on: every upward write passes through the tree. There is no arc from one spoke to another going out.

The word doing the work is “bulk”

The rule protects against a write of unbounded extent: one where nobody can say beforehand what will be different afterwards. A whole database is such a write, and it is the thing cwp does not do.

Individually named items may travel out of the tree, under the full guard set, with every affected item printed before the write. cwp push replaces global classes and named pages on a protected environment. Nobody calls either a breach. The only structural difference between a global class and a page is which table the row sits in. So the rule is:

Bulk database state moves toward this machine only. Individually named items may be written out of the tree, under the full guard set, with the affected items listed before the write.

Direction lives on the effect, not on the command

This part makes the guard list complete rather than remembered.

Every operation declares its effects. Each effect says whether it writes locally or remotely, and which side it lands on: the tree, the local site, or a remote. The protected-environment refusal reads that declaration. So it fires on push, deploy, inventory apply, bricks push, content push and content pull. The last one reads into the tree and writes one marker back out of it.

A guard keyed on the command’s name would have missed that last one, and would have gone on missing it. A guard keyed on the effect cannot: the marker write declares writes: "remote", and a structural test fails the build if an effect that declares it does not call the refusal.

The manifest’s own flow field does not change this. Each command declares which way it moves things so that the manual can draw one arrow per page without anybody typing it. Nothing in the tool reads that field, and a structural test holds the line. A command has several effects and a summary of them is not a plan. A guard keyed on the summary would wave a downward crossing’s marker write through.

What that costs, honestly

cwp pull against a protected environment needs --force in the cases where it writes at all. That reads as absurd until you know what those writes are: the uid of anything it adopted and the hash of what it took. Both are writes to a production database: a spoke, not the tree. cwp says so rather than exempting them because their command reads pull.