Proof and checkpoint formats
Use this page to inspect stored completion evidence or implement checkpointCheckpointA review question presented when a relevant kind of change occurs. integrations. For help deciding what a Proof means for your change, start with Proof.
| Find | Go to |
|---|---|
| Read a landed change's evidence | Proof notes |
| Fetch or publish notes between clones | Carry notes between clones |
| Parse the durable JSON record | Proof note format |
| Inspect the worktreeWorktreeA separate working copy and branch for one effort.'s current Proof marker | Worktree gate Proof marker |
| Interpret a checkpoint state or declarationDeclarationThe agent's recorded answer to a checkpoint question. | Checkpoint state and declarations |
Author a when command |
Checkpoint when protocol |
Proof notes
§With local Proof notes enabled, which is the default, acceptance attaches completion evidence to the landed commit under refs/notes/discern. The note remains available after temporary worktrees are removed and adds no trunkTrunkThe shared branch that accepted work joins, usually main. commit.
Read the current history with:
git log --notes=discern
Read one record with:
git notes --ref=discern show <commit>
discern status reports a valid local or fetched trunk-tip note as data.landed_proof: commit, source ref, and Proof.
The durable format
§The note separates structured evidence from its presentation inside a version 1 DSSE-compatible envelope. It contains no runtime telemetry. signatures: [] means the record is unsigned; discerndiscernA tool that installs and runs an agent development practice in a project. performs no signature verification. The format and reading rules below define the fields required for usable evidence and how readers handle unsupported records.
Replay keeps the first presentation
§The write identity is the explicit subject commit plus the stable machine-readable Proof claim. Repeating a note write with changed Proof-line wording, Markdown, or runtime timing returns already_present and leaves the existing note bytes unchanged. A different stable claim for the same commit remains a conflict and returns record_failed.
Authorship and failure
§The notes commit uses discern <[email protected]> as author and committer. With DISCERN_NO_ATTRIBUTION set, it uses the repository's Git identity instead. The Proof still records.
The completed trunk transition remains landed if note publication fails. Each acceptance queue row carries its note and pending state; the agent retries the recorded publication without repeating the transition or spending authority again. Setup results expose data.proof_note.write and data.proof_note.fetch.
Carry notes between clones
§Local recording changes no remote transport. To carry Proofs between clones:
[repository]
proof_notes_mode = "fetch"
Refresh or lifecycle convergence adds this mapping once per remote:
+refs/notes/discern*:refs/discern/remotes/<remote>/notes*
The trailing * keeps ordinary fetch usable when the source ref is absent. Git treats a wildcard with no matches as an empty fetch, so git fetch succeeds before the remote's first Proof noteProof noteA durable copy of landed Proof, attached to the commit in Git. and after that ref is deleted.
The mapping reserves the refs/notes/discern* prefix. Matching sibling refs receive matching suffixes under the tracking path. Proof readers ignore those siblings and consume only the exact refs/discern/remotes/<remote>/notes ref.
An ordinary git fetch updates the tracking copy. discern never configures remote.<name>.push, changes plain git push, or starts a network request. A landing then gives the publication command:
git push <remote> refs/notes/discern
Acceptance merges fetched refs/discern/remotes/*/notes histories before writing. A publish race can still reject a later push. Recover with:
git fetch <remote>
git notes --ref=discern merge refs/discern/remotes/<remote>/notes
git push <remote> refs/notes/discern
GitHub stores the ref but does not render it. Git-native readers and discern consume it.
Current state and gotchas
§- A note covers only the ref you read. Remote publication remains explicit.
data.landed_proofreports a readable note that is bound to its commit. This read path performs no signature or issuer-identity verification.- Direct Git inspection shows a Base64 payload. Use
discern status --verbosefor the rendered Proof. - A normal fetch keeps a stale tracking note after the remote deletes it. Run
git fetch --prune <remote>to remove refs the remote no longer carries. - Refresh reconciles the canonical exact mapping discern owns. Any other exact mapping stays untouched.
- A note with a different stable claim on the same commit is retained as a publication conflict. Inspect the pending note result before retrying.
Proof note format
§A Proof note is a JSON Dead Simple Signing Envelope (DSSE). The published schema defines its complete contract:
{
"payloadType": "https://discern.sh/schema/v1/discern-proof-note.schema.json#/$defs/DiscernProofNotePayload",
"payload": "<Base64-encoded payload bytes>",
"signatures": []
}
The Base64 payload decodes to a UTF-8 JSON claim. This layout abbreviates nested evidence; the schema defines the complete objects:
{
"subject": { "commit": "<full commit id>" },
"proof": {
"completion": { "...": "complete candidate and evidence receipts" },
"branch": "…",
"trunk": "…",
"head": "…",
"files_total": 1,
"insertions": 1,
"deletions": 0
},
"presentation": { "line": "…", "markdown": "…" }
}
Contract
§| Envelope field | Type | Required | Contract |
|---|---|---|---|
payloadType |
string | Yes | Exact public schema id plus #/$defs/DiscernProofNotePayload. |
payload |
Base64 string | Yes | UTF-8 JSON bytes for the payload. |
signatures |
array | Yes | Zero or more { keyid?, sig } records; current unsigned writers emit an empty array. |
proof field |
Type | Required | Contract |
|---|---|---|---|
completion |
object | Yes | Immutable candidate and source, composition procedure, complete evidence receipts, policy, and executor facts. |
branch |
string | Yes | Validated effortEffortOne task carried through implementation and review: the work a worktree, its branch, and its submission all belong to. branch. |
trunk |
string | Yes | Trunk branch used by the gateGateThe configured checks a change must satisfy for ordinary completion.. |
head |
string | Yes | Validated commit id. |
files_total |
number | Yes | Changed-file count. |
insertions |
number | Yes | Added-line count. |
deletions |
number | Yes | Removed-line count. |
mode |
strict or report |
No | report is CI review evidence and is not landing authorityLanding authorityPermission for a particular change to join the trunk.. |
checkpoint_drops |
array | No | Bounded fail-open checkpoint accounts. |
standard_proposals |
array | No | Commit-bound pending standard proposals. |
When acceptance is present, its authority, consent, variances, and standard_proposals fields are all required. authority retains the claim and settlement used for the exact transition; either decision array may be empty. consent.source is conversation, standing-grant, or effort-grant; scopes is optional. Each variances[] member contains checkpoint, definition_hash, subject, and why. A standard proposal contains standard, commit, bound_commit, measured_commit, definition_fingerprint, trunk, trunk_commit, direction, trunk_limit, proposed_limit, measurement, delta, reason, and non-empty evidence_paths.
payloadTypeidentifies the contract and compatibility major.payloadpreserves the serialized claim. discern writes padded Base64; its reader accepts standard and Base64url alphabets, with or without padding.signaturesholds Base64sigentries with optionalkeyid. A standard signed envelope has at least one. discern's unsigned extension has none.
subject.commit is the full commit; proof is the closed claim; presentation holds its line and page. Optional checkpoint_drops retains bounded failed-open accounts. Optional standard_proposals retains pending decisions. commit is the immutable config-only origin. measured_commit is its measured parent. bound_commit is the current measured descendant. The remaining fields give fingerprint, limits, measurement, delta, reason, and paths. Optional proof.mode identifies report-only evidence and is omitted for strict Proof. Acceptance never writes report-only evidence as a landing Proof. The writer excludes waited_ms and other telemetry. A future signature can authenticate presentation; policy decisions use the structured claim. Optional issuer assertions and brief support later provenance work.
Normal acceptance adds settled authority, consent, variances, and approved standard_proposals. A proposal-bearing claim without matching acceptance remains pending; generic consent approves none.
Write replay identity consists of subject.commit and the canonical proof claim. presentation differences return already_present and do not replace the standing note. A different canonical claim for the same subject is a conflict.
Signature and identity boundary
§The future signature input follows DSSE protocol v1.0.2:
PAE(UTF8(payloadType), decoded payload bytes)
The verifier uses those bytes directly; parsing and serializing the JSON could change them. Policy interprets only proof.
discern neither signs nor verifies today. A later profile chooses the algorithm, encoding, key lookup, and trust policy. keyid is an unauthenticated lookup hint; issuer fields gain meaning only when policy trusts the signing key.
Reading rules
§- Require
subject.commitand abbreviatedproof.headto match the noted commit. - Accept additive v1 fields throughout the envelope and payload.
- Report an unknown
payloadTypeasdata.landed_proof_unsupported. - Require the envelope, split
proofandpresentationblocks, an explicit subject, andsignatures, including the empty unsigned extension. - Accept standard or Base64url payload alphabets, with or without padding; current writers emit padded standard Base64.
- Treat proposal fields as structured landing evidence only when the Proof claim and acceptance evidence both carry the approved records.
- Require complete candidate evidence and, when acceptance is present, its settled authority. Missing prelaunch fields make a note stale; report-only evidence cannot become landing Proof.
data.landed_proof means the note is readable and commit-bound. This path performs no cryptographic verification.
Worktree Gate Proof marker
§The local marker links a clean authored source to the exact candidate and complete evidence used for completion. It supports reuse while those facts remain current.
The worktree-local marker resolves with:
git rev-parse --git-path discern/gate-proof
Its registered JSON format is version 1:
{
"version": 1,
"head": "<full commit id>",
"mode": "strict",
"completion": {
"candidate_id": "<candidate id>",
"proof_id": "<complete Proof id>"
},
"proof": { "...": "the structured Proof and both renderings" },
"evidence": "<checkpoint declaration evidence identity>"
}
| Field | Meaning |
|---|---|
head |
Full authored source commit, checked before and after completion. |
completion.candidate_id |
Immutable candidate validated for this source. |
completion.proof_id |
Complete evidence record in shared repository storage. |
mode |
strict for landing evidence; report identifies report-only evidence where present. |
proof |
Structured Proof and its renderings, including the live standard-proposal set when applicable. Its head names the validated candidate. |
evidence |
Checkpoint declaration evidence identity. |
The authored head and the Proof's head name the same commit: completion validates the invoked checkout's own committed tip. CI report runs provide feedback without landing Proof, and a report does not replace valid strict evidence.
A record missing completion, proof or evidence cannot narrow standard measurement, satisfy gate reuse, or skip acceptance validation. A text marker without a version is missing evidence and requires a fresh discern done. A marker with a version newer than 1 is retained and reports that discern must be updated before it can be used or replaced.
This worktree-local cache disappears with the worktree. After landing, the Proof note preserves the evidence on the landed commit when note recording is enabled.
Checkpoint state and declarations
§A checkpoint pairs a deterministic trigger with a questionQuestionSomething the agent is asked to judge about the project or a change. the agent judges. Completion reads governing definitions from [checkpoints] at the candidate's expected predecessor: the trunk's current tip. CI reports use their declared comparison policy. This commit supplies the policy identity every report and Proof names. A stop checkpoint pauses discern done for a recorded conclusion. An advise checkpoint presents the question without blocking.
Open question states
§A fired stop checkpoint opens an effort-scoped open question — the record a declaration binds to, carrying the resolved-definition hash and the subject fingerprint of the matched content.
Reopening is relevance-sensitive: a declaration stales only when the checkpoint's definition or the matched content changes. Unrelated edits and trunk advances leave it standing.
Once a structural trigger opens a question, a later trigger veto does not close it while that id still governs in stop mode. Its current subject and declaration determine whether a conclusion is needed. A recorded question outside the governing policy remains visible as history and does not block completion.
Strict obligation states
§Each governing checkpoint has an obligation describing whether completion needs a conclusion before gate jobs:
| Obligation | Strict meaning |
|---|---|
none |
No checkpoint conclusion is required. |
will_open |
The settled trigger will open its question and require a conclusion. |
awaiting_declaration |
A persisted open question already awaits a conclusion. |
reopened |
Subject or definition currency requires a fresh conclusion. |
declared_met |
A current declared-met conclusion lets the gate proceed. |
declared_unmet |
The gate proceeds; landing remains bound to an owner-authorized variance. |
unknown |
Store, subject, diff, or a pending when condition keeps the read decision unknown. |
Declarations at the gate
§discern done --met <id> (repeatable) records a declared-met conclusion; discern done --unmet <id> --why "<rationale>" records a declared-unmet conclusion, one per invocation, with a required rationale of 1–500 characters in one paragraph. A declaring invocation records every valid conclusion first, then proceeds into the gate in the same run. Recording a conclusion is the caller's own act; every surface qualifies it as declared met or declared unmet — recorded judgment, distinct from machine-verified results. The Proof carries declared conclusions separately, and changed declaration evidence stales a recorded Proof even at an unchanged HEAD.
Variance at acceptance
§A current declared-unmet conclusion makes discern accept refuse until the owner authorizes each named variance in the current conversation: discern accept --confirmed --variance <id> (repeatable; the id set must equal the declared-unmet set). Recorded standing and effort grants cover no variance. Each authorization binds to the exact declaration (checkpoint id, definition hash, subject fingerprint, rationale) and to the landed commit.
Read surfaces
§discern checkpoints (CLI, --json, --markdown, and the MCP tool discern_checkpoints) reports the governing policy with each checkpoint's canonical obligation, question, trigger summary, open-question evidence, and structural preview, plus recorded questions outside the governing policy, observed economics, and fail-open advisories. discern prepare and discern status expose checkpoint obligations as advice; discern done --dry-run previews them. This checkpoint inspection runs no configured when command and writes no question, declaration, gate marker, or checkpoint lifecycle observation. An undecided condition reports unknown and “may require.” The other configured preparation steps may still change files. Command details live in the CLI reference, executable input and output in the when protocol, and the result contract in MCP tools & results.
Checkpoint when protocol
§A structurally holding checkpoint may delegate its final firing decision to when = "<command>". An actual strict or CI run creates one temporary UTF-8 JSON file for the command and exposes its absolute path as DISCERN_CHECKPOINT_INPUT. Version 1 has this shape:
{
"version": 1,
"checkpoint": { "id": "example", "mode": "stop" },
"policy_commit": "<governing policy commit id>",
"changed_files": [
{
"path": "src/example.ts",
"kind": "modified",
"insertions": 4,
"deletions": 1,
"binary": false
}
],
"history": { "count": 2, "fingerprint": "<ordered-history hash>" }
}
changed_files is sorted by path and contains the final structurally narrowed changed evidence. Each kind is added, modified, or deleted; line counts are non-negative integers and binary is a known Boolean. history is optional and, when present, describes the ordered commit list from the governing policy commit to the evaluated revision. The object contains no raw file content, environment dump, question, rationale, or secret.
The registered input file has mode 0600 and exists only while its command runs. The fixed wall-clock budget is 10 seconds and retained protocol output is capped at 256 KiB. discern removes the file after fire, pass, invalid exit, timeout, cancellation, spawn failure, or input failure, completing cleanup before an interrupt can be re-raised. A cleanup failure or output beyond the cap fails the checkpoint open and leaves a typed drop. discern checkpoints, status, prepare, and dry runs create no checkpoint input file and run no when command.
Exit 0 fires and exit 10 passes. Every other exit, spawn or input error, cancellation, timeout, cleanup failure, or output overflow is indeterminate. When the structural trigger holds, an indeterminate stop serves its question against the complete structural matched set and records the typed uncertainty; an indeterminate advise checkpoint remains non-blocking and reports it. Proof with an indeterminate stop is not reusable, and acceptance requires current-conversation confirmation rather than a recorded grant.
On a decisive fire, DISCERN_MATCH <path> lines may narrow the matched set but cannot admit a path absent from changed_files. Without a valid declared match, the command retains the structural matched set.
The governing policy commit supplies the command text. During strict completion, that is the candidate's expected predecessor. The command runs in the candidate worktree, where its scripts, dependencies, configuration, and interpreter resolve. Those dependencies are not independently frozen with the policy command.
Implementation references
§These sources define note storage and publication. The published schema above is the integration contract.
Where it lives in code
§| Concern | Source |
|---|---|
| Note, merge, and transport | proof_notes.ts |
| Acceptance boundary | lifecycle.ts |
| Setup acceptance boundary | setup_accept.ts |
Where it lives in code
§| Concern | Source |
|---|---|
| Envelope, payload, issuer | result_schemas.ts |
| Writer, reader, cross-check | proof_notes.ts |
| Published schema | discern-proof-note.schema.json |