The artefact shapes any Cognitive Delivery implementation must read and write identically, plus a conformance corpus that proves it does.
Version 1.0.2, versioned independently of any product that implements it.
Two products will read and write .cdf/ artefacts in the same customer repository, and both
contribute to one Cognitive Delivery Index. If they record governance differently, the Index
stops being an index and becomes two unrelated numbers.
A TypeScript interface is a definition only while every consumer is the same codebase. This is the definition when they are not.
The corpus is the portable artefact. The runner is a reference implementation. A product
written in another language reuses fixtures/ unchanged and writes its own runner.
| Schema | Covers |
|---|---|
provenance |
What produced a governed artefact |
audit-event |
One line of the append-only governance journal |
cdi-signal |
One line of the Index signal log |
cdi-assessment |
A recorded human assessment against the six dimensions |
config-core |
The part of .cdf/config.yaml every implementation must understand |
agent-lease-manifest |
What an agent declares it needs before the harness lets it run. Specified normatively in SPEC-agent-lease-manifest.md |
agent-lease |
The signed grant the kernel answers with; the only key that opens anything |
plugin-manifest |
A plugin's plugin.json: every Claude Code key, plus the additive cdf block |
plugin-marketplace |
A marketplace's marketplace.json: every Claude Code key and all seven source forms, plus a per-entry declared digest |
- Lifecycle phases.
phaseis an open string everywhere it appears. The phase vocabulary belongs to the domain: software delivery has requirements, design, tasks and implementation, and another domain will not. A reader must tolerate an unrecognised phase — not throw, not coerce it to a known value, not drop it. - Product-specific config. Deployment assurance, security centre and template settings are
one product's business.
additionalPropertiesistrueat the config root so a product carries its own sections without failing the shared contract. - Implementation. This is data and generated types. There is no logic here and no dependency on any product.
plugin-manifest and plugin-marketplace are strict supersets of Claude Code's two formats.
Every key Claude Code defines is honoured with the same meaning, so a plugin written for Claude
Code validates here unchanged, and a plugin written for CDF remains a valid Claude Code plugin.
The only addition is an optional cdf block.
Two consequences follow, and both are deliberate:
- All seven source forms are declared, including three the harness cannot fetch.
npm,archiveandcommandvalidate and are reported as an unsupported source form. A reader that threw on them would refuse an entire marketplace over one entry nobody asked to install. nameis the only required key in a manifest. That is Claude Code's rule, and adopting it is what makes "validates unchanged" true rather than nearly true.
Almost everything here is open. Two things are not:
cdi-signal.event_typeis a closed enum of 127 values. The Index is computed from this vocabulary, so a product adding a value changes what the Index measures. That should be a contract change, and this makes it one. Governed by ADR-013.- The six CDI dimension ids. They are the instrument.
By contrast audit-event.event_type is open: the journal records what happened, and a
product may record its own kinds of event without changing what anything measures.
config-core.sealed lists fields an upper layer has fixed. An implementation that ignores it
fails conformance. A lower layer may match a sealed value or make it stricter, never looser.
Ignoring this would let a workspace quietly undo a control its organisation set.
Additive only. New optional fields are allowed.
Renaming a field, removing a field, narrowing a type, or changing the meaning of an existing field requires 2.0.0 and a documented migration. Customers have these files in their repositories and older readers will still be reading them.
This is not a promise in a README. schemas.lock.json holds a normalised digest of required
fields and property types, and a check fails the build when the rule is broken without a major
version change.
The comparison is against the shape before the change, not against the lock sitting beside the schemas: a lock regenerated in the same commit agrees with whatever broke it. On a pull request the baseline is the branch being merged into; on a push it is the previous commit.
Every artefact carries schema_version. One without it is read as 1.0.0.
npm install @cognitive-delivery/contract
Releases are published from CI through npm trusted publishing, so each one carries a provenance attestation linking the package on the registry to the commit and the workflow that built it. A contract that asks other people to record what produced an artefact should be able to show what produced its own.
You can also use it straight from this repository, as a submodule or a clone pinned to a tag.
schemas/ and fixtures/ are plain files and an implementation in another language needs
nothing else.
A child agent asks for less than its parent holds, and gets less again than it asked for.
The parent lease grants a broad scope:
{ "allow": { "tools": ["cdf_read_steering", "cdf_write_artefact"],
"read_paths": ["**"], "write_paths": ["src/**"],
"hosts": ["*.anthropic.com"], "commands": [] },
"deny": { "commands": ["sudo"], "paths": [".cdf/runtime/**"], "hosts": [] },
"budget": { "tokens": 200000, "depth": 2, "fan_out": 4 } }A worker declares what it wants — note it asks for one tool the parent does not hold, a host the parent does not allow, and more tokens than remain:
{ "schema_version": "1.0",
"agent": { "name": "implementer", "kind": "delegated-cli", "runtime_agent": "claude-code" },
"intent": { "purpose": "Implement task 1.1 within its file scope.", "spec_slug": "phase-9", "task_id": "1.1" },
"allow": { "tools": ["cdf_write_artefact", "cdf_break_glass_advance"],
"read_paths": ["src/**"], "write_paths": ["src/projects/**"],
"hosts": ["api.anthropic.com", "example.com"], "commands": [] },
"deny": { "commands": [], "paths": [], "hosts": [] },
"budget": { "tokens": 500000 },
"approvals": [] }The issuer grants:
{ "allow": { "tools": ["cdf_write_artefact"],
"read_paths": ["src/**"], "write_paths": ["src/projects/**"],
"hosts": ["api.anthropic.com"], "commands": [] },
"deny": { "commands": ["sudo"], "paths": [".cdf/runtime/**"], "hosts": [] },
"budget": { "tokens": 200000, "depth": 1, "fan_out": 4 } }Reading the difference:
cdf_break_glass_advanceis gone — tools intersect by exact name, and the parent never held it.example.comis gone — the parent's*.anthropic.comdoes not contain it.api.anthropic.comsurvives — the parent's wildcard contains it.src/projects/**survives — the parent'ssrc/**contains it, so containment keeps a genuine narrowing rather than dropping it as an exact-match miss would.tokensis clamped to what the parent had left, not what the child asked for.depthis decremented: this worker may issue one further generation, not two.- The parent's
denyentries are inherited although the child declared none. A child cannot shed a refusal.
Nothing about the child's identity opens anything. The lease id does.
The full rules, including the six conditions that require a refusal, are in SPEC-agent-lease-manifest.md.
npm ci
npm test # the corpus, against the reference adapter
npm run check:additive # the lock is current, and this change is additive
Both run in CI on every push and pull request, against Node 20 and 22. The point of a corpus is that a third party can check the claim, so the check has to be runnable by someone who has never seen the product.
npm test also runs the canonicalisation vectors, and this is the part worth reading before
you write an implementation in another language.
Every hash in this contract — declared_hash, every signature, the ledger chain — is taken over
canonical bytes. Schema agreement is not interoperability: two implementations can accept and
reject exactly the same artefacts and still produce different bytes for the same declaration, and
therefore be unable to verify a single one of each other's signatures. Everything looks correct
right up until somebody else's hash arrives.
conformance/canonical-vectors.json holds nine vectors with their expected byte strings and
SHA-256 digests, plus two values that must fail to serialise. Supply a canonicalise(value)
on your adapter and the runner checks them; omit it and the run reports NOT CHECKED rather
than passing quietly. The rules themselves are section 7 of
SPEC-agent-lease-manifest.md — the escape set is closed, keys sort
by UTF-16 code unit, and an absent member is omitted rather than nulled.
These are not stylistic. Audit and Index evidence is append-only and retained indefinitely, so anything that reaches it is effectively permanent.
- Prompts are never recorded.
prompt_hashandrequest_hashare SHA-256. workspace_idis a hash of the git remote URL, not a person identifier.- The actor records a kind — human, agent or system — and the model. Never a name, email or git identity.
detailsis sanitised before write: keys matching token, secret, password, authorization, prompt, content, file or path are dropped. Renaming a sensitive field to evade that check defeats the control.
schemas/ the JSON Schemas, one file per shape, each self-contained
fixtures/valid/ minimal and fully populated, per shape
fixtures/invalid/ each beside a .reason file saying why it must be rejected
conformance/ the reference runner; takes an adapter, imports no product
runner.mjs the corpus, run against whatever adapter you pass it
ajv-adapter.mjs the reference adapter, so the corpus runs here and not only in a product
canonical-vectors.json the canonical-bytes vectors of SPEC section 7, in pure ASCII
run.mjs `npm test`
schemas.lock.json the recorded shape, and what the additive-only guard compares against
check-additive.mjs that guard
Apache-2.0 — the schemas, the fixtures, the conformance runner, all of it. See LICENSE.
Permissive on purpose, and Apache rather than MIT for one reason: the patent grant is what makes an organisation comfortable implementing a format. A format a third party can write to, and prove conformance against, is what makes the Index citable rather than merely used.
The corpus is included deliberately. Schemas without fixtures let someone claim conformance; schemas with a corpus let them demonstrate it, and let anyone else check the claim.
The implementations remain PolyForm Noncommercial 1.0.0. Reading and writing the format is open; building a competing governed-delivery product out of this codebase is not.