Rendered from docs/decisions/0072-the-binary-is-the-only-interface-an-adopter-must-run-and-every-integration-point-outside-it-is-declared.md in the Headwater
corpus. Every document on this half of the site is typed by the taxonomy
the descriptor names: corpus.json.
The binary is the only interface an adopter must run, and every integration point outside it is declared
Context
An adopter installs this engine to govern a corpus that is not this one. What that adopter has to run has never been written down. Everybody assumed the answer was headwater and nothing else. Three measurements show that the tree does not hold the assumption.
No verb writes a change manifest. headwater check --change reads one, and the contract names .githooks/change-manifest as "the producer this repository uses". That shell script is the only producer that exists, and it belongs to this repository. A run without the flag states the cost. At e4a63da1, 729 rule instances of this corpus report change-scoped-only, which means that no rule reads the prior version. The report calls them skipped, so an absence reads as a posture.
headwater init scaffolds a consumer declaration and an overlay, and nothing else. The merge driver that protects a derived artifact needs a git config line and an executable in the adopter tree. HW-DR-0049 states that an adopter inherits the rule rather than the artifacts, and #892 asks whether that answer still holds.
The front door instructs a script. README.md and step 3 of the tutorial both name tools/headwater-bootstrap.sh, and the tutorial states that the script is not a part of this engine. Here the binary already reaches the same result, because headwater taxonomy vendor takes the path of a fetched artifact and an expected digest.
No document states the boundary. The eleven principles in spec 0 do not name it. Principle 8 says that the system governs itself, which is why this repository carries scripts at all, and it draws no line for an adopter. The command surface indexes the verbs and never claims that they are the whole surface. So the rule was a shared assumption, and an assumption that nothing holds is one that prose drifts past.
Decision
An adopter runs the binary for every operation of the governed loop. The loop is what reads the corpus, checks it, writes it and resolves its taxonomy. A corpus owner reaches all of it through headwater, and this repository proposes no script to an adopter for any part of it.
One integration point sits outside the binary. This list is closed against growth.
- Git plumbing. A merge driver, a merge attribute and a hook are things git runs. Git does not take an executable from a repository without the consent of the clone, so the engine cannot install one. #892 rules on what ships inside this edge.
A network fetch left this list. headwater taxonomy vendor took a path and never a location, on the ground that no crate of this engine opened a socket. HW-DR-0075 rules that the no-socket property serves the checking loop alone, and that a bootstrap verb runs outside that loop. It also rules that the digest in --expect already makes a fetch safe whoever performs it. vendor now accepts a location, since #1064 landed the fetch for #959. The fetch lives in a crate that only the CLI links. So this is a correction of the entry, and not an exception granted to it.
The test for the edge is necessity and never convenience. An integration point is legal here only where the binary cannot do the work without the loss of a property the corpus depends on. Git plumbing meets the test, because consent of the clone is not a property this engine can grant itself. A point that fails this test is a defect, and a missing verb is a gap to file rather than an exception to grant.
The change manifest is inside the binary. headwater change writes the manifest that headwater check --change reads, from the two anchors that spec 12 fixes. So the manifest is not an integration point outside the binary, and it has no entry in this list. #929 is the issue that built the verb.
This list grows by a decision record and never by a script. A contributor who reaches for a script in adopter-facing prose either finds the verb or files the gap.
Consequences
An adopter who runs headwater check --change gets the manifest from headwater change. No script stands between the adopter and a change-scoped check. .githooks/change-manifest only hands its two arguments to that verb, for the hooks of this repository.
#892 gains a frame it did not have. Its question was whether merge-safety tooling ships at all. The question now is narrower. The edge is legal, and consent of the clone is the constraint on it. What remains is what ships inside it.
#930 landed too. README.md and the tutorial now name the binary route first, and call the bootstrap script a convenience over it rather than the only route. vendor now takes a location directly, since #1064 landed it under HW-DR-0075. The path form is still worth documenting, because an adopter on a mirror or an air-gapped host needs it either way.
The list is closed against growth and not against a correction. HW-DR-0075 removed the second entry, and a list of one is the stronger form of this ruling rather than a retreat from it.
#933 answered what should check this record's one remaining claim. A corpus-wide rule was rejected. The list holds one necessity-based entry. So a rule that reads every document for a stock lexical pattern would report zero findings by construction. That is the failure shape a lexical rule already takes when its targets run out. .claude/tutorial/adopter_interface.py checks the narrower, real risk instead. It reads README.md and the tutorial for a script this repository ships standing in for a verb. Both #929 and #930 took that shape. It names the bootstrap script's network fetch as the one declared exception. .claude/tutorial/fixtures.sh runs it in CI. As a result, a second edge added in silence now fails a check rather than waiting on this record staying short enough to read.
This record rules on what an adopter runs. It rules nothing about what this repository runs for itself. Principle 8 keeps tools/ and .githooks/ exactly as they are, because a corpus that governs itself needs producers that no adopter ever sees.