Skip to content

Join

Criteria. Order sets of criteria by inclusion: a set that contains another constrains everything the smaller one does, and more. In that order, the join of two sets is the smallest set that contains both. That is their union.

Union has the three properties that make order irrelevant. It is the same whichever set arrived first, the same however several sets are grouped, and a criterion that arrives twice, by two routes, counts once. So criteria that reach an artifact-set by different routes, in any order and any number of times, combine to one set.

This is the order-theoretic reading of the lattice, and it is what confluence rests on.

Status: Settled.

The join is not taken over states. The states that meet a set of criteria are usually several, the way a truss can have several stable equilibria, and none of them is least. Two routes can settle in different states that meet the same criteria, and neither is wrong.

That is why confluence is claimed over criteria. A join over states would promise one settled state, and criteria rarely determine one.

Status: Settled.

The two answer different questions, and they belong to different frames.

Connection Join
Reading of the lattice The graph: sets and the edges between them The order: sets of criteria under inclusion
What it is A declared relation between two artifact-sets An operation that combines sets of criteria
Frame How the system is set up How a run proceeds
Failure Strain: the relation does not currently hold Conflict: no state can meet the combined criteria
Resolved by A workflow restoring the relation A recorded decision

Connections say where criteria flow. The join says how criteria that reach the same place combine. An artifact-set with one connection receives one set of criteria. An artifact-set with several must meet the join of everything they bring.

In the bug-fix example, {code, test} has two connections. Through {spec} it receives the page count rounds up and an empty list shows one page. Through {mockups} it receives the page indicator looks like this. The code has to meet the union, and the union is the same whichever workflow finished first.

Status: Settled.

A run can change the criteria it combines. When the intent amends a criterion, the new one replaces the old, and the old one leaves the set. That is not a join, and it is not a conflict.

In the bug-fix example the spec states round down, plus one, and the fix’s criteria say round up. Joined, the two would contradict each other, and every fix would become a conflict no replay can restore. They are not joined. Feature delivery amends the spec, the old rule is gone, and only the new one takes part in the join at {code, test}.

The join combines criteria that stand together. Telling a replacement apart from a contradiction is judgement. It is the same judgement that separates a new criterion from a reversal under a new name, and the same controller makes it: the specification set’s controller.

A replacement removes a criterion from the set’s standing specification, so the write that makes it contradicts that specification, and the leash decides whether it needs approval. By default it does. A fix to a stated rule and a deliberate change of direction look the same from inside the set, and nothing in the run can tell them apart without judging the intent, so the default treats both as a change an approver accepts. A team that finds the stop is ceremony for a set loosens that set’s leash.

Status: Settled that replacement is distinct from join. Thesis that the leash governs it. Open: how a controller tells a replacement from a contradiction.

A conflict is a join no state can meet. Two criteria stand together and contradict each other.

Suppose design update runs with a designer in the loop, and the designer adds hide the page indicator when there is only one page. The spec already says the indicator always shows the total page count. Each criterion reaches {code, test} through its own connection, and each could be met alone. Together they disagree about a list that fits on one page.

The strain appears on connections, but its cause is in the join, so no workflow can restore it. Whatever the code does, one of the two connections stays strained, and running the workflows again only moves the strain from one to the other. A conflict needs a recorded decision. The decision settles which criterion stands and creates the next version of the criteria.

This is also how the join bounds a run. Oscillation between two workflows is often what an unresolved conflict looks like from outside, and conflicts are finite: each pair of contradicting criteria is decided once.

Status: Settled that a conflict is resolved by decision, not by replay.

The join holds within a run. There the run’s criteria are frozen as a version, and a new version comes only from a person adding criteria or from a recorded decision. Criteria the specifications held before the run take part only where a replacement the leash let through does not remove them.

Between runs a specification changes freely. Criteria are rewritten and removed, and the next run starts from whatever the specification then says. Holding criteria to append-only across runs would be too restrictive. What is append-only is the record of how each version replaced the last.

Status: Settled.