Gates
A claim about the code that is not a test is a box someone ticked. CVN ships its gates as functions so a repository's tests can assert them against its own files.
Purity
import { checkPurity } from '@enc-protocol/cvn/gates'
const violations = checkPurity({ 'kernel/a.ts': srcA, 'kernel/b.ts': srcB }, {
exempt: { 'kernel/host-glue.ts': 'the one file that names the platform, by design' },
})
assert.deepEqual(violations, [])Forbidden globals: window document localStorage sessionStorage navigator fetch setTimeout setInterval XMLHttpRequest WebSocket Buffer process require __dirname. Forbidden members (not namespaces): Date.now Date.parse new Date Math.random performance.now. Strings, template literals, comments and regex literals are stripped before matching — /failed to fetch/ once counted as two uses of fetch. An exemption without a reason throws.
Port contracts
import { declaredInInterface, declaredByDestructure, suppliedInLiteral, diffPorts, untravelled } from '@enc-protocol/cvn/gates'Three failures, each silent at runtime, each named here: a declared port nobody supplies (missing), a supplied port nobody declares (extra), a declared port nobody travels (untravelled). Wire all three into the repository's fast tier.
No capability gates
Not shipped as a function — it is a grep, and the shape matters more than the mechanism. Two patterns, refused across every family:
- reading
.submit(or any write capability) off a port, and - resolving an adapter by enclave id.
Both are the same defect: asking a port whether a write would work, when the write is a Cmd whose performer already refuses an unroutable one by name. Ten instances were found in one application; six of them resolved an adapter to ask, which allocates. On its first run the gate found three more, one of them feeding a variable nothing read. See the rules.
A model per family that decides anything
The measure that says a port is finished also says the formalization is:
- every family with a run has
Families/<Name>.lean— the file name derived from the family name, so a new family is covered by default and a renamed one fails rather than going quiet; - it has a corpus kind the oracle emits;
- and a replay that imports the module it claims to replay. A corpus replayed through a copy proves the copy.
A family that declares NO_RUN and empty PORTS is exempt: it takes no click
and decides nothing.
Log gate
node tooling/log-gate.mjs <log> [...] refuses a run whose captured console contains a TypeError-class message, an unrouted Cmd, a failed unwrap, or a ladder rejection — de-duplicated and counted. An exemption is a regex with the spec's name and the reason, never a wider pattern.
Certificates
node tooling/certify.mjs check | run | hash <tier> — see Testing cadence.