Connections
The hole is at the connections
Section titled “The hole is at the connections”Every artifact-set has a controller, and most of them are
good. The compiler holds {TypeScript files}. Biome holds formatting. Astro and Starlight
hold {website content}.
None of them reach past the set they hold. And the couplings that matter most run between sets:
| Connection | Owner today |
|---|---|
| Starlight stylesheet → components rendered beneath it | nobody |
a skill → four vendor manifests + the files list |
prose in AGENTS.md |
| version field → four manifests | scripts/sync-plugin-version.mjs, hand-built |
| an accepted ADR → the module it governs | nobody |
The gap is not at a level of granularity. It is at the connections, uniformly, at every level. That single observation is what unifies the CSS-correctness thread and the plugin thread in this repository’s backlog: they are not adjacent bodies of work, they are the same one.
Status: Settled.
What a connection relates
Section titled “What a connection relates”Two artifact-sets, at their specifications rather than their implementations. There is no diff between a TypeScript module and a Figma frame, so a connection stated over implementations could never be evaluated; stated over criteria, both ends are written in one vocabulary.
Status: Settled. The argument is on the Specification page.
Connections are undirected
Section titled “Connections are undirected”A connection is a relation between two artifact-sets. It is not an arrow.
SDD’s {spec, suite} and {code, test, stories} are connected. The mission loop
traverses that connection spec-first; backfill traverses it implementation-first;
build-to-learn works both ends at once. Three traversals, one relation.
Direction is a property of where the delta landed, and of the workflow that restores the relation, not of the connection. Writing direction into the connection bakes in one workflow and makes the others second-class — which is precisely the situation the model exists to fix.
Status: Settled.
Declarative, never procedural
Section titled “Declarative, never procedural”A connection states a relation that must hold. It is never a handler that fires.
This is the most expensive commitment in the model to reverse, because every connection ever written encodes it.
The reason is confluence. If a connection is “when the spec changes, run this to update the implementation,” then backfill needs a second script for the reverse direction, and nothing makes the two agree. Two entry points, two code paths, two results, and the guarantee is gone before the first connection ships.
Stated as a relation, propagation means restore the relation in whichever direction is strained. Same relation, same fixed point, any entry point.
Status: Settled.
Kinds of strain
Section titled “Kinds of strain”Strain is a connection whose relation does not currently hold. Working the two axes against real cases produced three distinct kinds, and the examples added a fourth. They behave differently. A strain is exactly one of them, so each is named for the defect rather than for the property it falls short of.
Incompleteness
Section titled “Incompleteness”Intra-unit-of-change. Add a skill, also wire four manifests and the files list.
That is one commit; the strain is that the change is incomplete right now. It gates, and it blocks.
Obligation
Section titled “Obligation”Between units of change. An accepted ADR obliges the module it governs.
These are deliberately separate changes — decide now, implement later. The strain is not “you forgot,” it is “this change created a debt.” It does not block, but it must be tracked and discharged traceably.
This kind was the last to be identified, and it explains an artifact already sitting in
the repository: docs/backlog.md is a hand-maintained obligation ledger. Not all of
it — some entries are genuinely new ideas — but the ADR-obliges-module chain and several
others are debts created by earlier changes, recorded by hand because nothing generates
them.
It also gives declining a home. Declining is how an obligation is discharged without being done, and without it any report nags forever.
Nonconformance
Section titled “Nonconformance”Axis 2. This skill violates the agent-instruction guidelines.
State-driven, evaluable on a cold repository, and requires no delta.
Missing
Section titled “Missing”Implementation ahead of its specification. A bug fix introduces a rule the spec never stated.
A controller above the change, asked in a workflow the change bypassed, answers that its set lacks a criterion the change’s intent implies. The implementation now meets something its specification does not state, and the specification is the side left behind.
Missing strain is relative to a change, which the other three are not. Every implementation shows behaviour nobody wrote down, and most of it is coordinates. Missing strain fires only for criteria a change’s intent introduced, and it is found when a controller derives them from that intent. A set too coarse to hold the criterion is not missing it; the question passes to the set above. A refactor introduces no criteria and strains nothing.
The first three are not an arbitrary list. Read through the specification relation they are the three ways a specification and its implementation can fail to meet from the specification’s side: both in hand and disagreeing, the implementation elsewhere, or no implementation in the delta at all. Missing is the relation read from the implementation’s side. That derivation is on the Specification page.
Status: Settled that the first three are distinct and block differently. Thesis on missing, found by the bug-fix example. Open: the precise boundary conditions on each, and how missing strain blocks.
A missing connection is found outside the run
Section titled “A missing connection is found outside the run”A run settles against the connections that are declared. A controller answers for its own set from the criteria it is referred to, and a criterion reaches a set only through a connection. Where a connection should exist and does not, no criterion arrives, every controller answers correctly for what it was given, and the relation the connection would have held quietly fails.
The insulin example shows the shape. The accreditation standard is connected to the hospital policy, which lets each unit name the steps that need a second nurse. The standard is not connected to the unit’s protocol. A unit drops the check from routine rate changes, the policy still holds, the protocol only adds, and no leash fires. Declare the missing connection and the standard’s requirement reaches the protocol, the protocol write contradicts it, and the leash stops it.
A run cannot detect what the topology does not declare. That is not a defect of the run. It is the limit of settling against a declared topology, and a guard written inside one set would only patch a relation nobody declared. Missing connections are found by an audit loop that runs outside normal operation and reads across sets, comparing practice with the standards above it. An audit is a scheduled controller whose run is a change, the shape of the compliance audit in the catalog. Its finding is a connection to declare, or an obligation against a set when nothing can restore it yet. SDD runs its outer loops the same way, beside the mission loop rather than inside it.
Finding the topology is iterative. Each audit that finds a missing connection makes the next run catch what this one could not.
Status: Thesis. Open: what an audit loop reads, how often it runs, and how its finding becomes a declared connection. See Open questions.
A coupling that resists encoding
Section titled “A coupling that resists encoding”The clearest evidence that controllers cannot all migrate to deterministic code comes from a defect in this repository’s own docs site.
An element declared top: 0rem rendered 16px lower than intended. Starlight’s markdown
stylesheet gives every element following a sibling a 1rem top margin, and an absolutely
positioned element offsets its margin edge — so the box sat 1rem down while
getComputedStyle reported top as exactly 0px, in perfect agreement with the source.
Every static check passed. The value was wrong anyway.
The attempt to push this coupling down to deterministic code makes it worse: stylelint’s
length-zero-no-unit would have autofixed 0rem → 0, leaving the defect intact and
destroying the only forensic tell. There is no mechanical rung beneath render it and
measure.
This is why the controller spectrum has an agentic end, and why the plugin is not an optional convenience.
Status: Settled — the case is verified against this repository’s configuration.