Artifact-sets
Artifact
Section titled “Artifact”An artifact is one type of thing in a repository. Not one file, and not one line — a type.
TypeScript files. CSS. Website content. Repository configuration. A skill. AGENTS.md.
The choice of type rather than instance is load-bearing. This repository ships
plugin.json, .claude-plugin/plugin.json, .cursor-plugin/plugin.json, and
.codex-plugin/plugin.json — four files, one artifact. A rule keyed to files has to be
written four times and rewritten when a fifth vendor appears. A rule keyed to the artifact
is written once.
Two levels, and the model only ever names the second. Four files are one artifact —
plugin manifest — and that artifact is one member of the set that has to move when a
skill is added. A rule written against the right-hand box survives a fifth vendor
appearing in the left-hand one.
Below this level the coupling is already owned: symbol and reference coupling is the compiler’s job, and reproducing it would produce a worse compiler.
Status: Settled.
Two axes
Section titled “Two axes”Artifacts group into artifact-sets, and they do so along two axes that are orthogonal. A group on one axis need not be a group on the other.
Axis 1 — unit of change
Section titled “Axis 1 — unit of change”Artifacts that must move together for a change to be complete.
{code, test, stories} is the canonical example: an implementation that changes code
without its tests is not a smaller change, it is an incomplete one. In this repository’s
terms, a unit of change is what belongs in one commit to be coherent.
This axis is delta-driven. It is meaningless without a change, and it asks: did this land everywhere it had to?
Axis 2 — governance target
Section titled “Axis 2 — governance target”Artifacts that the same criteria apply to.
{a skill, AGENTS.md} is the canonical example: the same agent-instruction guidelines
govern both, though neither obliges the other to change.
This axis is state-driven. It needs no diff at all — a cold repository can be evaluated against it — and it asks: does this conform to the criteria that govern it?
Why they must stay separate
Section titled “Why they must stay separate”The axes disagree in both directions, and collapsing them loses information.
Adding a skill does not require touching AGENTS.md, so {skill, AGENTS.md} is a
governance target and not a unit of change. Code and tests co-vary tightly, but the
criteria governing a test differ from those governing the code it exercises.
The two axes drawn over the same repository. Neither set contains the other and neither
is a refinement of the other — they cross. skill is the only artifact in both, and it
is in them for unrelated reasons: it moves with the manifests, and it is judged by the
same criteria as AGENTS.md. Collapse the two ellipses into one and you get a set that
is wrong on both counts — it would demand AGENTS.md change with every new skill, and
it would hold the manifests to guidelines written for prose.
truss therefore takes both a delta and repository state as input. They are not the
same query and neither subsumes the other.
Status: Settled.
Controllers
Section titled “Controllers”Each artifact-set is held consistent by a controller, on a spectrum from agent definition to deterministic code.
Lifting
Section titled “Lifting”Git reports a change as lines in files. The model speaks in artifact-sets. Nothing can be matched until the delta is lifted — raised from a line diff into the set vocabulary.
Lifting is a distinct operation and, on current reading, a distinct subsystem. It is a prerequisite for everything downstream: an unlifted diff cannot be matched against a connection, because the two are written in different languages.
Status: Settled that lifting is required. Open: where it lives and how much judgement it needs.