docs/prover/,
which this page links down to rather than repeating.
On hosted deployments, the Prover’s estate live-progress WebSocket follows the
deployment’s hosted identity boundary. A signed hosted assertion must resolve to
an active explicit identity link for the configured tenant and installation before
the channel is admitted; a later expiry or revocation closes the channel. The
API Reference
documents the connection parameters and close behavior.
The division of labour
Agents submit and poll
Register estates, characterize them, prove a pair, author and repair
specifications, grade them, ask for rulings, and read every result back. An agent
reaches all of it either through the REST API or, inside Genesis, through its own
tools — the same service underneath, not a second door.
People read and approve
The Prover workspace is a monitoring surface and an approve-button surface.
You are not asked to push micro-buttons that do micro-things; that altitude
belongs to agents. For a pinned license that needs re-confirmation, the finding
history read exposes whether
reconfirm_license is currently offered and the
evidence signature it would bind; show that action only when
license_reconfirmation.offered is true (API reference).view_connections allowlist. For a user-started
mission, Prover reads use the mission originator’s visibility where that originator can
be verified; cancel_run remains scoped to the originating conversation. The exact
read verbs, caller-scoped visibility, authority limits, exclusions, and refusal behavior
are documented in the
Prover toolkit reference.
Estate setup is agent-driven as well as estate monitoring. An agent can register an
estate, edit its definition, attach git code assets, clone those repositories, and derive
their transform lineage before it characterizes the estate. The exact parameters,
replacement rules, and force behavior are in the
Prover toolkit reference.
A run an agent started is an ordinary run: same address, same words, nothing marked
differently because a machine asked for it. What can tell you an agent was involved is
its provenance — which surface the work arrived on, which identity it acted as, and
which authenticated person was behind it.
How much of that a given run carries depends on the surface that started it. A
specification-authoring run records all of it today, along with the doctrine it was
pinned to;
How a run works
sets out provenance in full, including which run types carry which part of it on the
current build.
A grade started through the prover_tools group records surface: "tool" in its
provenance. That is the audit distinction for a direct agent tool call; it is not a
different grading path or a different verdict.
A clean table is not yet a proven pipeline
The Prover now separates what is in the target from what produced it. A clean comparison still answers whether the measured rows and structure agree; its additivewriter_attribution summary answers whether every target relation was attributed to a
re-runnable mechanism. Read the per-relation writer_readings when the summary is not
fully attributed. An unmeasured writer reading is not a failure of the table
comparison, but it does mean the result cannot be read as evidence that a pipeline
produced that relation.
The reading comes from the target engine’s own write history, and Databricks is the only
one of the fourteen supported dialects that exposes one. For a Databricks reading of
unattributable, the Prover can also use Genesis’s own completed Flow-step record: when
the step wrote the same relation on a connection bound to the target snapshot, and the
engine’s last-write time falls within the step’s run (with two minutes of clock skew),
the reading becomes attributed with mechanism: pipeline and includes flow_run.
On every other engine each relation reads unmeasured carrying that engine’s own reason,
and the summary’s basis then says so rather than describing a hand patch nothing measured
— so read basis, not the qualifier alone, before reporting what produced a customer’s
tables.
For a specification that requires a particular producer, use a written_by obligation;
it grades the target relation’s write history and accepts only the declared job,
notebook, or pipeline mechanisms. For a pipeline demand, it uses the same completed
Flow-step attribution described above: where the target engine exposes per-relation write
history, a matching flow_run can attribute a write that history names even when it does
not name the pipeline. A Flow-run record cannot substitute for an engine with no write
history; finalization refuses such a written_by obligation (refusal details).
Writer history is necessary evidence, not sufficient proof: a patched table can still be followed by a successful rerun. The
reproduce_artifact tool
is the sufficient check; it runs the declared SQL artifact in a utility estate and
reports whether its output reproduces the live relation. Its REST contract is
POST /api/estate/estates/{estate_id}/artifact-reproduction.
An agent can decide an eligible Prover Action Review request for a person who asked
or delegated it; other approval requests still refuse and return a link. See
Roles and approvals
for eligibility and the approval record.
Discover before you trigger
When an agent starts with identifiers from the estate surface rather than snapshot or run ids, it can discover the existing work before launching anything new. Thefind_proofs tool should come first when the question is whether a migration has already
been checked: it accepts the names, connection references, or database names a person
uses and returns the proof of record with its current review decision; for the exact
stands values, including the unmeasured null case and the rule to treat only true as
signed off, see the Prover toolkit reference.
If a new proof is needed, list_snapshots resolves an estate id to its scan timeline and exposes the
snapshot ids that prove and compare require. Its rows distinguish scans bound by a
scan event from snapshots matched by the estate’s registered scope; the latter are
inferences, not asserted bindings. If a recorded decision no longer binds to the
comparison’s current population, the proof still reports that decision with a measured
non-standing basis rather than making it look as though nobody ever decided. Exception
standing is based on the final state in the review log, so an exception that was
retracted and then re-approved does not leave the approval withdrawn. A re-diagnosis is
different: it withdraws the run decision and the basis names the finding and time that
caused the comparison to await review again. See the
Prover toolkit reference for
the exact review_decision fields, boundary-group resolution, non-asserting resolution
contract, and the unattributed_snapshots disclosure for snapshots withheld from proof
pairs. If
data.resolution.asserted is false, choose one candidate with active: true and ask
again; do not relay the empty pairs list as proof that no migration was proved. The
proof rows also hand over the Human Review page that records the decision; use
review_url and review_url_basis as documented in the toolkit reference rather than
constructing the address yourself. Relay review_url exactly as returned, including the
whole hash; use review_path exactly as returned only when review_url is null. Without
a public base URL, a link may use the Genesis address the conversation came from or this
server’s local dashboard address; use it only in the context named by its basis. When no
usable address is available, review_path carries the page’s address relative to the
Genesis dashboard. Do not relay the deployment setting named by review_url_basis to the
person signing off. A
standing run decision is not the same as whether a comparison is Verified or needs a
sign-off; use read_comparison and its data.review.nothing_to_decide field for that
question, as described in the tool reference.
The list_runs tool shows recent work newest first,
so an agent can check whether a characterization, comparison, or other run is already
in progress or complete after a bounded wait expires. The same cross-conversation
visibility boundary applies to get_run and runs submitted with notify=false; see the
tool reference. Run listings
and run-backed reads follow the caller-specific estate and comparison visibility in
Prover result visibility.
The same visibility governs other Prover reads and actions, including rulings on
proofless-grade reviews. See the
tool-specific episode and court behavior.
Pass estate_id when the question
is about one named estate; it matches proofs submitted under that estate or compared
against it as the target, before pagination. The response’s runs_without_estate count
discloses runs with neither a submitting estate nor a resolved target estate. See how
runs are listed
for the estate-filtering edge cases. That feed is a page, not the whole ledger: inspect
has_more and pass its opaque next_cursor to continue through older runs. These are
read-only discovery steps; they do not start a scan or another proof. For scan-time row
counts, use read_snapshot rather than counting against the live connection; its full
response contract is in the toolkit reference. A scan summary’s
schemas_scanned_count and schemas_discovered_count count schemas, not tables.
schemas_discovered_count is null when a pinned scope remains explicit_subset. With
estate_char.characterization.full_source_default enabled (default true), a pin naming
exactly the schemas included by the full-source scope is recorded as full-source instead.
That whole-estate pin keeps the same boundary as an unpinned full-source scan, so it does
not re-key findings. If full-source scanning is disabled or schema discovery fails, the
pin remains an explicit_subset. The earlier scanned_count and discovered_count
spellings remain for one release; they also count schemas, but discovered_count counts
a pinned list as discovered.
For completed comparison history, list_comparison_events provides a bounded,
newest-first discovery feed; inspect its truncated result before assuming all
comparisons are present. Its response shape and drill-down route are defined in
the Prover toolkit reference
and estate API reference.
See the estate API reference for the rule that
keeps customer proofs out of curated Estate workspace labels.
The proof also discloses estate movement separately from population standing: read
source_moved_since_approval and target_moved_since_approval to see whether either
estate has CHANGED since the snapshot the approval was recorded against. A change does not
withdraw the approval; it tells the reader that the approval concerns an older estate
reading. count counts later readings whose measured content differs from the bound one, or
could not be compared with it — not later readings, because a re-scan of an untouched
estate still writes a new snapshot row; readings_since carries that raw number for an audit answer. The movement blocks are
always present and carry a basis, so no_standing_approval, no_snapshot_bound, and
approved_snapshot_absent are not silently presented as a clean count of zero, and
no_content_change names an estate that was re-read and measured the same. See the
toolkit reference for the exact block fields and basis vocabulary.
For a new scan, characterize(estate_id=...) binds the work to the registered estate;
the complete parameter and refusal contract is documented in the
Prover toolkit reference.
Direct scans accept every dialect registered by the Prover, including SQLite and the
other engines listed in that toolkit reference.
When the schema picker is populated for a SQLite estate, it lists the databases
attached to that connection; the temp database is excluded. See the
estate API reference
for the discovery contract.
One trigger: the proof
A proof is a comparison, optionally graded against a sealed specification — and it is one call either way. The agent brings the two sides; if it also holds a sealed specification, it names it, and the same proof grades that specification against the comparison it just produced. When a table is specified in parts, compiled-spec grading also accepts a set of two or more sealed specification hashes. The parts are graded as one result: each column is owned by the member that covers it, overlaps and conflicting claims are reported inspec_set, and
only columns no member covers remain drift. The exact request, response, conflict rules,
and warehouse-work implications are in the compiled-spec grade API reference.
When the structural tier finishes, read summary.spec_set_reading to relay the same
members, seals, overlaps, conflicts, and uncovered differences the review card shows.
That single trigger is the point. The proof owns its children and names them, so nothing
is hidden and no identifier has to be threaded between calls by hand — and the grade is
bound to the comparison this proof produced, because a verdict attributed to the wrong
comparison is worse than no verdict.
The proof is also the notification owner: a comparison or grade child that finishes while
its proof is still running is reported through the proof’s terminal wake, not as a second
thread notice. The Prover toolkit reference
covers the bounded form used when that wake enters a mailbox.
The trigger also accepts row_identity when the engines do not declare a business key;
a key position may be a coalesce expression when the key is carried across more than
one source column. See the proof request contract for concat positions.
On a spec_hash proof that is not using a relocation premise, omission of
case_insensitive_object_names or row_identity inherits that value from the estate
pair’s latest successful proof of the same spec. The pair is the resolved source and
target, not the caller identity; an explicit request value always wins. The proof records
the requested and effective values in summary.proof_addressing, with a source of
request, inherited, or default for each value. When case policy was left to the
deployment default, the completed comparison records the resolved value with source
config, so a later proof keeps the policy actually used rather than following a changed
configuration. The record also keeps case_insensitive_object_names_origin: "config".
When a re-prove omits that policy and the inherited value differs from the deployment’s
current setting, proof_addressing.differs_from_config records compared_under and
configured_now; the pair keeps its prior policy, and basis explains that the caller
must pass a value to change it.
There are two exceptions to straightforward inheritance. A proof retried with the same
client_request_id and the same requested values reuses that submission’s addressing,
even if the pair has since had another successful proof. Also, if a later proof was
refused with row_identity_unusable when comparing under the prior proof’s row identity,
that row identity is not inherited again; omit it to use the engine-declared basis. The
case policy still inherits in this case. proof_addressing records prior_proof_run_id,
differs_from_prior, row_identity_refused_since_prior, and a basis sentence explaining
the decision.
When a declared key repeats, the refusal’s remedial call can suggest a more useful
identity instead of only telling the caller to remove it: add columns that distinguish
the repeated rows, use a first-non-NULL coalesce key, or provide separate source and
target key terms when the two sides identify the object differently. The exact tool
argument examples are in the Prover toolkit reference.
When a declared key cannot be read on one side, that is different from a key the estate
read and rejected as unusable. A terminal proof refusal reports the distinction in
summary.unverifiable_objects, with the object, side, and probe cause; its next keeps
that declaration and tells the caller to make the estate readable as the submitting
identity or omit the declaration if it cannot be fixed. A key verified as unusable is
listed in summary.unusable_objects and removed from the remedial call. The synchronous
comparison endpoint returns the same decision in its 400 payload.
During grading, invariant reads and grain probes use the registered query transport for
the bound connection. An estate exposed through a Connections API transport can therefore
be graded even when the legacy DatabaseConnector does not own that connection; the
API reference
defines the binding fields and validation.
For the shared-connection catalog rule for target-side invariants, including the
one-database-per-connection exception, see the API reference.
That reference also documents the admission-time 400 for a one-database engine given
a catalog other than the side’s recorded snapshot database.
Attaching a sealed specification is an authority act: it takes the same authority a
person needs to ratify, and an agent without it is refused before anything runs — not
even the comparison, so nobody pays for the expensive half of a proof that could never
have been finished. Roles and approvals
covers that permission.
The proof’s tier-selection admission rule and its terminal-run remedy are defined in the
API reference.
Comparison cards in chat
prove, compare, get_run for a proof or comparison, and read_comparison carry a
top-level presented block for the chat surface. The dashboard renders it as one
comparison card rather than asking the agent’s prose to reproduce the result. Other
answers carry presented: null; it is not part of data.
When a comparison was created with a business title, the Prover landing and Human
Review use it as the headline and retain the technical source → target label beneath;
legacy comparisons without one keep their existing technical headline. The API’s
comparison-list field is documented in the API reference.
When Judge now starts a new no-spec comparison from a spec-titled card, see the
API title rule for how
the submitted title is stamped. See also API title handling for no-spec
reuse.
Separately, read_comparison may return data.timing_rescan_evidence when the comparison
has timing-cause abstentions. Treat it as evidence, not a revised verdict; see the
read_comparison guidance
for its interpretation and limits, including how it places re-scans across changed
observation boundaries. For a large reply, check the preview for this evidence before
reading spilled output; the tool guidance describes the serialization order and its truncation
limit.
For a comparison-only compare response, data.with_a_sealed_spec is present when
the caller should use a sealed spec for grading. It tells the agent to call
prove(spec_hash=...) with the same pair for one comparison-and-grade, or to call
grade(spec_hash=..., diff_hash=...) when a separate grade is needed; relay that
guidance rather than treating the comparison as already graded. The target-model
recompute and its cost are described in when a grade names a comparison made without
its spec.
The card starts as Comparison running and is updated in place when a poll or wake
reports the same run. A completed card carries the explained (licensed), unexplained
(unlicensed), and could-not-be-measured (indeterminate) counts, plus the count of
reads that could not be read (errored) when that value is not zero. When the run
withheld readings because the target was Data Vault-shaped, or because no objects paired
on either side without a declared model, the card carries the guidance needed to declare
the mapping and may carry withheldUnlicensed and withheldIndeterminate; each zero
published count uses the headline format in the comparison guidance.
That guidance also explains how withheld readings differ from unexplained and undecided
readings. A read_comparison card can be the newest measured payoff verdict in any shape,
including scope, when its errored count is measured; an unknown count does not qualify.
See the read_comparison tool guidance
for how that count is supplied for scope. When the review
population also carries nothing_compared: true and no spec_grade, the approval action is
unavailable even if its members are all accounted for. Follow nothing_compared_cause: declare the mapping
for undeclared_target_shape, check that the target snapshot matches the declared mapping
and re-prove for declared_mapping_matched_zero, rerun when the matched count is unavailable,
or re-prove with a schema_map for matched_zero. The approval refusal and review-card
readiness use the same cause, so the remedy shown to the person is consistent. A reshaped build — one whose spec derives
the target from the source, so no table pairs — is judged by its spec grade instead: when the
population carries spec_grade, a verified grade makes the comparison approvable once nothing
is open, and an unverified one is refused with spec_grade_not_verified, naming the grade’s
blockers. See the
review-population API fields.
When a verified person’s standing approvals cover every item that kept the comparison off
Verified, the card reads Verified, names the approved-item count, and identifies
approvers using their user display names when the server provides them. If a name is
unavailable, it uses the part of the recorded address before @ (or the recorded label
when it is not an address); the full address appears on hover rather than on the card face.
No separate run decision is required; the comparison can read Verified without a
run-level sign-off. A person’s explicit reset to awaiting_review remains a “not approved”
and keeps the card off Verified until a verified approval replaces it.
This reviewed outcome does not change the spec grade shown beside it; a grade still running
cannot be lifted to green. The outcome is withheld while an open behavioral catch remains.
The API’s person_acceptance conditions and item details are in the comparison review response.
A partial seal keeps its grade below Verified: the card reads Partially specified · N
clauses open (singular clause at 1), not Verified or “verified with unresolved
scope.” A grade whose seal kind cannot be read instead says Seal state unknown — details
on the review page; neither state is green. envelope.report_this includes the partial
label and names the open clause ids. The Prover review view lists each open clause’s reason
and remedy, including who must act; the grade run’s summary.open_clauses carries the full
clause, evidence and remedy. When the remedy belongs to the owner or operator, it also carries
the seat’s recommended_answer; that recommendation does not itself close the clause. Legacy
run rows may have no stored seal field; the
compiled-grade API reference
documents how Genesis assigns their reading.
A clause accounted for by the comparison of its objects (accounted_by: "scope") is decided
by each grade, not by registration. The grade proves it only when every named object was
measured on both sides and the comparison found it clean (match or licensed); a
file-measured dataset must match its landing file by file. Otherwise the clause is held open
for that grade, including when a side was not measured or the comparison errored. A grade that
compared no objects holds every such clause open. The grade view’s
clauses_proven_by_comparison lists the per-object result. An unproven clause appears in the
review as not proven by this comparison, with a remeasure remedy; a person may accept it
only if it is out of scope. See register_clause_accounting
for how to record this disposition.
Each clause is a separate open evidence-gap member. A person may accept a clause as out of
scope in review; that acceptance can let the comparison read Verified once every blocker is
accounted for, but it does not change the amber grade. An agent must not accept a clause or
ask a person to accept one whose remedy names the proposer. For proposer-owned clauses,
follow the remedy and commission a follow-up seal with repair_of=<partial spec hash>; for
remedies naming the owner or operator, ask that person once using the seat’s evidence and
recommended answer. See the tool reference
for the recommendation requirement.
For selected-check requests, see the grade tool reference.
A grade of only selected checks is distinct from a partial seal: its result reads
Partial grade · N of M checks and carries graded_check_ids and
spec_check_count to identify what was graded. In chat, the card reads Partial grade,
never Verified or green; the card does not show those counts. See the grade tool
reference for selecting checks.
For a running proof, the card also names the estate pair recorded on its run row, so the
chat can open the live comparison before a diff exists. When read_comparison presents
the completed comparison from that proof, its presented.proof_run_id names the proof
run; chat uses it to update the original running card rather than leave a second card
beside the verdict. The read_comparison read cost for that bridge is described in the
read_comparison tool guidance.
See the
Foundry verification guide
for how an asynchronous migration proof is returned and followed.
In the chat card, the newest comparison with a view opens the embedded Prover theater
while its run is active. It follows the proof into the comparison and stays mounted as
the result arrives; once settled, the same card shows its source-and-target Venn and,
when green, a migration pass score above the picture. The score reports object matches and behavior checks
available in the conversation; Certified requires the comparison to be green, all
counted objects to match, and every behavior check that ran to pass. If the theater is
unavailable, a static Venn is used when comparison evidence is available. Readers who
request reduced motion see the static Venn rather than the live theater. The score’s
Open in Prover link opens the detailed stage, so the card does not repeat its
Detailed view link. The theater’s snapshot picture uses the inventory shape of the
snapshot detail API, so it loads object and column names without loading the full
characterization document; see the snapshot endpoint reference.
When object_presence.not_built names a declared derived target the build lacks, the Venn
shows it separately as Derived table(s) not built; the list is outside the source-object
counts, and any entry prevents the payoff from showing green.
While the live theater is shown, its caption names the pair and its picture gives the
count after assumptions, so the card omits those duplicate lines. On a green comparison,
the theater’s verdict sentence also replaces the card’s verdict bar and count list; a
comparison that needs attention keeps those counts on the card. When the theater falls
back to the static Venn, the card returns to its own pair and verdict display, with the
assumptions count and disclosure when available.
When the completed comparison records assumptions, its headline uses
issues_not_covered_by_assumption, the count after those assumptions. If the
assumptions list is non-empty, the count carries an asterisk; select it to open the
assumption list and inspect each assumption’s statement, scope, basis, source, and
covered readings. From that list, a person can choose Withdraw for this pair and
confirm to stop the Prover relying on that assumption for the comparison card’s estate
pair; the withdrawal affects later comparisons, while this stored comparison keeps its
verdict. An empty list leaves the count unstarred, while a missing list leaves the
after-assumptions count undisclosed rather than treating it as zero. The same disclosure
is available from the comparison’s review and detail views.
When a comparison card would exceed the presentation size limit, Genesis keeps the card by
trying smaller assumption disclosures: it first omits assumption evidence and source,
then clips long statements to one line, and finally omits the card’s assumption list while
retaining the after-assumptions count. The comparison review page continues to show the
complete assumption records.
It also reports what changed since the previous comparison of the pair. A first
comparison says so; when unexplained findings decrease, the change line counts the
ratified rules that account for that decrease rather than printing their ids. When it
attributes a decrease to behavior proofs, it gives the proof count rather than printing
run ids. If the indeterminate count rises during
that shrink, the card does not claim that portion was explained: it says
N unexplained not measured this time and shows undetermined before → now. A partly
measured shrink reports the measured decrease and its rule attribution separately, then
adds N more not measured this time. When the recorded withholding differs between the
comparisons, their unexplained counts cover different populations: the line describes the
withholding change and shows both counts without claiming a shrink or growth. If one side
has no recorded withholding count, it says so rather than treating the count as zero.
Comparison history follows what the scans compare, not just their connections. Bound
scans remain grouped by their estate; an unbound scan joins a database’s sole boundary
group only when that estate’s scope admits the scan. If no estate or boundary group
identifies a scan of a known database, its requested schema pin distinguishes its
history: different explicit schema subsets on one database have separate histories,
repeated scans of the same subset stay together, and full-source scans remain grouped by
database. Within a history, changing the object or schema map does not start a new pair.
The previous comparison can come from another conversation. When it is from another
conversation, the card says so and includes the conversation id when available. If the
prior conversation was not recorded, the card says so; if its relation to the current
conversation is unknown, the card names it when possible and says its relation is
unknown. It omits the line when the prior comparison is from this conversation or the
server sends no conversation metadata.
When two comparisons differ only in declared scope and otherwise observe the same
databases in the same way, they share finding identity. Changing scope alone therefore
does not re-key findings for objects that remain covered. If a later scope does not cover
an open finding’s object, that comparison did not measure it and does not resolve it.
Comparison-linked writes from grading, stimulus rounds, source-drift reconciliation, and
dossier capture use the pair identity recorded on the diff when available, so findings
remain on that key after a scope change. Older diff records without a recorded pair
identity use their observed boundary pair.
The identity class includes each comparison’s observed boundary pair and its recorded
identity pair when those differ. If the class later files under another pair, findings
left open under the former pair remain there; they are not moved or closed. The findings
API labels these rows with superseded_by_pair to identify the pair now receiving new
filings; see the estate API reference.
Earlier rulings recorded under another scope can reappear in the current proceeding’s
prior_verdicts; the fetch_adjudication_materials contract
defines the aliased_from field that identifies the key holding such a ruling.
When a completed run is measured against a named specification, its finished notice also
states what clarification records that specification relies on and who recorded them.
That sentence comes from the sealed provenance, not from the ticket’s wording; a seal
created before clarification records existed reports that clarification provenance is
unknown. A finished proof or comparison notice also names its review page when one is
available. When the notice gives both a markdown link and a plain dashboard path, relay
both exactly as given and do not shorten the hash: the link opens in the Genesis
dashboard, while the plain path is available to people receiving the message in Slack
or Teams. The fields and fallback rules are in the toolkit review-link
reference.
A grade can be not verified even when every structural item is confirmed. The
conformance scope is part of completeness. An unmet scope expectation always blocks;
an unnamed target object blocks when the scope claims the whole target by carrying
same or changed objects across. When the scope names only objects built by this
change (for example, new tables), unnamed objects already present on the target are
reported in scope_unclaimed but do not block: the spec makes no claim about sibling
tables. Unnamed source objects absent from the target are likewise reported in
scope_unclaimed_absent, not as missing-target blockers and not as licensed absences:
the scope says nothing about whether these source objects should be carried over. This
report applies only to object-grain absences under the comparison’s own pairing; named
source objects and column-grain differences remain subject to attribution. In that
build-only scope, object-grain comparison abstentions do not add an
indeterminate blocker for a new or input object (or an object the scope does not
name): the scope’s own presence verdict decides named objects, and unnamed target objects
remain scope_unclaimed. An undeclared schema map likewise does not add an indeterminate
finding when the scope claims only a build, because the spec declares no source-to-target
pairing. When a same or changed entry carries an object from a source schema the target
does not hold and no schema_map or object_map addresses it, that entry is instead
indeterminate with cause: "schema_map_undeclared"; the comparison cannot establish
where it went, so it is not graded as not_implemented. The schema_map_unpaired summary
groups those scope expectations with the unnamed target objects and missing/surplus
readings attributable to the same absent map. Its target objects are excluded from
scope_surplus, and the review population represents the missing map once rather than
once per affected scope entry. A map must name the target schema each source schema became;
use an object_map when the object names also differ. Column-grain abstentions remain
indeterminate because scope states presence, not content; abstentions also remain when the
scope carries objects across. Missing target objects named by the declared scope remain
measured and can still block. The headline names both kinds of unclaimed objects without
treating them as blockers.
Integrations can use the structured scope status, expected treatment, and target
presence on each scope blocker in the review population rather than parsing its
basis text; see the comparison review population response.
When a full-seal grade is verified_with_indeterminate and unconfirmed changes remain
without a failed item or recorded failure, every surface labels it Not enough evidence
and says the remaining items need a person. This is an amber result, not a verified one.
A verified grade with unconfirmed changes remains Not verified; partial or unreadable
seals use their separate wording.
The grade also asks for a person’s decision on a target column that is new and nobody
accounts for. scope_unaccounted_columns lists object.column coordinates on tables the
scope builds or carries when the column is absent from the relevant source and is named by
no spec item, sealed check, declared mapping, or target model. For a carried table, the
paired source table supplies the comparison. For a split image, the target model’s
declared columns on that image supply it; if the model declares no columns for the image,
the split’s source table supplies the fallback. A column the split drops, sends to another
image, or whose source never held it is therefore new on this image unless another surface
accounts for it. For a new table with a target model, the model’s declared columns are the
complete answer. Without a model, a new table is read
against the scope’s named input tables; if there are none, the grade reads against every
source table and reports that limit in scope_unaccounted_limits, and if none of the named
inputs are on the source, the limit says no source columns were available to carry.
An unlicensed target-only column_surplus on a changed or new table leaves drift and
appears in this list; on a same table it remains drift. These columns are not reported as
failures: the grade can read verified_with_indeterminate while the card names the pending
decision, and the Prover flow marks them unaccounted in its pending tone. In Human Review,
each column is an evidence_gap with cause target_column_unaccounted; approving its
exception package records that a person accepts the columns as expected, while a spurious
column must be sent back as a defect. scope_unaccounted_readings lists the exact unlicensed
column readings withdrawn from drift for that decision. The blind findings and canvas keep
each in the unlicensed population with unaccounted: true; no item detection or licence
claims it as explained.
For a palantir_foundry estate, a scope entry may name a dataset by its bare RID,
such as ri.foundry.main.dataset.<uuid>, even though the scanned catalog name includes
its folder path. Genesis resolves that RID to a catalog name ending in the RID,
case-insensitively, only when the supplied spelling is absent from both inventories and
exactly one candidate exists across them. It uses the resolved name consistently for
scope verdicts, surplus-object accounting, and finding attribution. If there is no unique
candidate, or resolving entries would make two scope entries claim the same object, the
entry keeps its supplied spelling.
Conversely, a confirmed structural removal with no attributed obligation reads as
pass with basis: "confirmed_by_diff"; the diff itself is complete evidence for
something that is gone, so the item is not left grey as unverified. These removals now
count in coverage.items_pass rather than coverage.items_unverified; the grade adjusts
those two item counts to agree with the confirmed item verdicts. Read the item’s basis
when explaining why a grade passed or remained unverified.
A failed structural item is not an unknown: its blocker says failed and names the
spec check ids in failed_by. The grade headline groups those failed items by check and
keeps “could not be confirmed implemented” for items no check or structural oracle
decided. If an item failed structurally without a named failed check, the reason says
not implemented or implemented differently from the spec; only an undecided item
uses “could not be confirmed.” The grade response reference describes the corresponding
failed_items counts and failed_by review-member field. When the grade has obligations,
its headline also names structural changes not yet confirmed that were not already counted
as blockers: it distinguishes changes with no covering spec check from changes whose checks
reached no verdict. These remain separate from failed-item counts. In the flow view, an item
the grade marks unverified and attributes no check to is unverified, not a pass merely
because a traced check read or keyed on its column; see the API Reference
for the flow fields and count.
The card is green only when the comparison has zero unexplained, indeterminate, and
errored reads, no readings are withheld, and the measuring run did not report
clean: false. A missing count is not treated as zero. Refused runs show the Prover’s
reason, including the known pairing reason when nothing was compared; if unresolved blockers
also exist, the refusal names them alongside that reason. Failed runs say that the comparison
did not finish; neither is a verdict.
The card provides Review findings and Detailed view links for a completed
comparison; Detailed view falls back to the comparison’s Venn view when estate
coordinates do not resolve.
When a specified grade stands for a comparison whose tables paired, the card takes its
verdict and counts from that grade, as the review Overview does, rather than from the raw
table-comparison verdict. Its accounting reports the grade’s explained, unexplained,
indeterminate, and errored counts; source tables outside the spec’s scope are named
separately and are not counted as unexplained. A pending grade is shown as still being
graded, without table counts. A verified paired grade is green only when it measured its
drift and the grade’s errored obligations plus the comparison’s errored reads total zero.
A reshaped build whose tables paired none continues to take its verdict from its spec
grade without table counts. See the read_comparison guidance
for the presented.spec_grade fields and read cost.
For a grade of a derived build whose source and target share little by
identity, clients can request a flow view to trace ordered output columns back to
the source columns named by the spec and checks, and to account for target columns
declared by the sealed target_model. The view distinguishes columns derived by
that model from columns whose lineage a spec check establishes; see the API
Reference for their states, source-column
readings, and counts. When the grade carried no
specification, the view explains why there are no spec-ordered columns to trace rather
than failing; see the API Reference for that response
shape. For how the flow view attributes failed checks—including table-name resolution,
ambiguous unqualified names, incomplete traces, and SQL dialect selection—see the
flow endpoint reference. For spec-backed
flows, the source and target captions name the dialect and
database recorded on the snapshots the grade compared. Call it when opening the flow,
not as a run-progress poll. When only the counts are needed, request shape=summary; use
the default shape=full to show the traced columns, checks and snapshot tables. Summary
still reads the inventories and parses SQL to count item states, but avoids producing and
transferring the detail lists. The comparison stage uses scope preserved in the
spec_conformance run-list summary to choose the Flow or Venn view and explain why;
see the list_runs tool guidance
for those summary fields.
Check-only reads of scoped source inputs appear as comparison references, not unread inputs;
the API reference defines the column-level status behavior.
Comparison cards defer their undeclared-target withholding caveat to the proof response
contract.
Clarification review is deliberately after reliance. A person may ratify an agent-made
clarification after a seal cites it; the seal then shows person-ratified provenance. If a
person overturns it or the recording agent withdraws it on the owner’s word, every seal that
cites it and every verdict measured over those seals reads reopened at read time. The
reopened run carries the cause in reopened and its outcome becomes not_verified, so a
previously green comparison is not presented as a standing verdict. The seat run that
produced the seal is not itself reopened. On the review page, an open finding last seen by
a verdict over that reopened seal is marked as resting on it, rather than shown as a live
failure of a standing verdict; the finding remains open and its history is unchanged. See
the ledger response fields; the
same notice is available when an agent reads the finding’s history with
read_finding. See also the
clarification review and reopened verdict API contract
for the exact fields and review permissions.
For how Prover finding reads handle hidden episode sightings, see the
read_finding contract.
When presented.kind == "comparison_card", answer briefly: state the status or verdict
only when the card carries one, ask at most one follow-up question when needed, and offer
“tell me more” for the long form. This keeps the agent response from repeating the
counts that the card already shows. The Chat and threads guide
shows the user-facing layout.
Four words you will see on a run
Handle
The id that comes back at once. The work is not finished when the call
returns; the handle is what everyone watches afterwards, and it outlives the
request that created it.
Waiting
A caller that would rather block than poll can ask the server to hold the response
for a bounded time. The ceiling on that wait is yours, not the caller’s, and a
request above it is clamped rather than refused —
How a run works
has the setting.
Timed out, still running
A wait running out is the caller giving up on waiting, never the server giving
up on the work. The run continues; only the response came back early. A proof
reads both estates in full — and a graded one reads them again for the
obligations — so a wait that expires on one is normal rather than alarming.
Refused
The system worked and declined: a seal that does not verify, a grading tier
nothing defines, a connection the deployment does not hold. A refusal is an
answer, and the run states its reason in words. It is not an outage, and it is not
something to retry unchanged.
docs/prover/prove.md
lists every status a proof can reach and what a caller should do about each. And as
everywhere else in the Prover, the status is not the verdict:
How a run works
covers that distinction.
An errored read is unmeasured
When the live re-read needed to decide a comparable table errors, the comparison emits anerrored element. This is not an indeterminate finding: indeterminate means the
comparison reached the data but could not settle it, while errored means the read
produced no measurement. It counts in neither the licensed, unlicensed, nor
indeterminate totals, and a diff with any errored element is not clean. Treat it as
an instrument or connection problem, using the SQLSTATE, retryability, and failure
basis in the comparison summary, rather than as evidence about the estates.
The single-comparison API exposes the same errored_reads and clean measurements,
plus any comparable_digest_refold disclosure; see the API reference.
For a graded proof, the grade view keeps this population separate from findings in
unmeasured_elements. Each entry identifies the failed instrument with element_id,
its comparison and object coordinates, and the read basis; cause is included when
the diff supplied a coded failure cause. unmeasured_elements_basis explains the
population. An empty list means every element reported by the diff was measured, while
null means the grade recorded no element population (for example, no grade ran or the
grade predates these fields). Do not treat an errored element as drift or as an
indeterminate ruling: it contributes to neither verdict count and the comparison is
not clean.
Read the verdict basis, not just the verdict word
Comparison summaries includeverdict_bases for the verdicts and named causes that
actually occur in that diff. match, licensed, and unlicensed describe measured
data; indeterminate describes a comparison that was not measured or could not be
attributed; errored means the read itself failed before measurement. For an
indeterminate element, use its cause and the matching entry in verdict_bases
instead of collapsing every abstention into one generic bucket. In particular,
cross_representation_precision_unverified is a float-versus-exact numeric boundary
that was not compared beyond float precision, and outside_characterized_scope is a
target surplus outside the source scan’s characterized boundary. boundary_not_numeric
means that a numeric column’s boundary summary on the named side was not numeric, so
the extrema could not be compared as quantities; inspect the column’s null and distinct
counts for the underlying values. A substitution can decide this boundary when the source
extremum is exactly the literal it rewrites and the target extremum is numeric. If a
structural item also catches the reading, it is attributed to those items instead of
remaining indeterminate only when every catching item states a change and the same
substitution accounts for the column’s entire content-digest movement, including its
null-count change. Otherwise the reading remains indeterminate. instrument_void means a
person previously ruled the instrument’s reading at that finding’s locus an
instrument_defect; a later proof
honours that standing ruling as indeterminate instead of re-minting the same finding as
unlicensed. For findings whose ledger identity does not include detail, the resulting
element’s detail says it was voided, names the actor and ruling time when available, and
explains that the reading was withheld rather than re-charged; identity-scoped findings
retain their original detail so the ruling remains on the same ledger row. These are
instrument limits or rulings, not evidence that the estates differ.
When the target characterization declared an absence, the proof summary also carries
the declared absent_scope_basis and the measured absent_relations that support it.
The closed basis vocabulary is relocation and
frozen_build_did_not_produce. The former means a decision-10 relocation has not moved
the declared relations into the round-0 target yet; the latter means the measured build
failed before producing them and is backed by build_evidence (armed_by, build_rc,
error_summary, before_side_measured, and offset-bearing measured_at). The proof
prefixes unmeasured_elements_basis with this cause only for elements over relations
actually measured absent, so those elements are reported as unbuilt rather than as
failed reads. If the absence licence cannot be read, the proof reports that unreadable
licence on the same basis field instead of silently treating the target as ordinary.
Rounds, and asking the same thing twice
Repair rounds are numbered from 0. Round 0 is the first build, and the number the caller submits is the number the proof reports and stamps on every measurement it creates. A run can also carry an episode round, which belongs to reconciliation episodes rather than to proofs — separate numbering spaces, and a proof is not an episode. Submitting the same proof twice does not run it twice. A repeat is answered by the proof that already holds the answer, marked as reused, rather than by a second run measuring the same thing again. That is why re-asking is cheap, and why a run list does not fill with duplicates when the same acting bot and authenticated user retry. A retry from another identity starts its own proof rather than receiving the earlier result. A run marked superseded is a different and rarer event — it is about the grade, when two different proofs arrive at the same one while it is still running. For the proof/comparison submission-identity split, including thecomparison_reused_basis disclosure and the round_n re-measure lever, see the
proof API reference.
For compiled grades, a reused response includes reused_basis, which explains what the
matching identity turned on. When it names the request’s estate_coordinate, the
earlier verdict is about the same measured estate. When no coordinate was supplied, it
states that the sealed spec, binding, round, and tiers matched but that the identity did
not establish that the estate submitted here is the estate the earlier run graded. A
fresh grade returns reused_basis: null; see the API reference
for the response field and the coordinate’s request semantics.
What a run reports back
Every run type answers at one address and in one shape, so nobody needs to know which workflow produced a run in order to ask how it is doing. What a reviewer leans on is the provenance stamped on it when it was created — which build served it, which doctrine it was pinned to, who ran it — and, on a proof, what it reports about its own loop: whether it certifies, which round it was, what regressed, and the source/target snapshot pair it certifies. Every timestamp backed by the estate store — not only the run envelope — is served as a UTC-aware ISO-8601 value; the API reference defines the snapshot and timestamp contract, including the malformed-timestamp exception.docs/prover/run-envelope.md remains the field-by-field shape reference.
For committed fork election results in a compiled-spec grade, including the
readings_not_taken and taken_verdict fields, see the grade response reference.
For the grade’s unadopted offers and per-obligation requirement_source provenance fields,
see the grade response reference.
Each obligation also reports which target tables its target_sql reads. If the grade cannot
parse that SQL in the target engine’s dialect, target_sql_unreadable gives the parser’s
reason rather than implying the check reads no columns; the API reference
defines the per-obligation fields.
Checked substitutions
A passing sealed check can license a narrow literal-to-NULL substitution even when the
spec declares no estate-wide value_substitution rule. This is not a license for every
passing check: the grade recognizes only a nondegenerate, outright-PASS keyed membership
check that reads one whole table on each side and compares the same column. Its target
expression must preserve that column while mapping NULL to a string marker; its source
expression must preserve the same column while mapping one string literal to that same
marker. A source-side TRIM around the literal test is allowed; a renamed column, bounded
text cast, or other expression is not recognized.
The check licenses only that literal becoming NULL on its compared source column, and only
when its target table is the comparison’s paired counterpart and row-check coverage for that
table is confirmed. For an ambiguity fork, only the passing member selected by the committed
lean can license it. The column’s decided column_content_digest must agree with the
substitution, and each licensed reading must be consistent with it; the check does not
license other columns, column_max_length, or categorical_value_counts. Finding rule_ids
names the proving obligation id, not an accepted_differences rule id. For the authoring-side
clause refs, see spec-author identity and constitution.
Reporting a completed run
Prover tool answers are for the agent to correct its work, not text to forward to a person. Decide who is reading and relay the relevant outcome in that person’s terms; a self-check gives the agent a to-do list, not a transcript for the person. In a live chat, ask only a business question that still makes sense without Prover terms and whose answer depends on that business; include a recommended answer. If the spec reserves ratification to the person, ask them to approve it even when the recommendation seems clear. In an unattended goal, mission or blueprint run, fix what the agent owns, record unresolved business questions with a recommendation, and continue with unblocked work; wait only when a person’s answer blocks a step. The Prover toolkit reference documents theaudience and audience_note fields on each answer.
A terminal proof or grade provides envelope.report_this as its record line. Use it as
the source for every report; do not reconstruct its verdict, counts, or ids from the
nested summary. Quote it word for word and label it as the record when reporting to a data
engineer, to anyone asking for the line, or in any record you write. In chat with a
business owner, do not quote it: give the plain-language answer, use only the numbers in
that sentence, and include the review link where the record lives. It names failing
obligation ids and full identifiers returned by the record, so do not supply an id that no
tool returned in the thread. A named failed check
includes (<mismatched_key_count> of <rows_compared> rows) when its mismatch count is
known and it compared at least one row; when that count is a floor, it is rendered as
at least N rather than as an exact measurement. When mismatched_key_count is null, the sentence
uses the key-probe sizing described for the failed-check headline
when available; other checks without a measurable size have no suffix. The report names up to ten failed checks,
plus an eleventh when it is the only one beyond that limit; when more remain unnamed, it
summarizes them as and N more and points to summary.verdict.failed_checks, where each
remaining check is named with its size. For grades, it also
names unmet-scope objects and every derived table excluded from the claim, with its
recorded exclusion reason or, when none is recorded, that no passing declared check
covers it. It reports how many items the review opened with when the grade carries that
population. This opening count is not the live number still awaiting disposition: read
the review for that. If you add your own interpretation
of a failure, put it in a separate sentence and label it as your reading; do not let that
interpretation change the reported tally. The sentence uses the grade’s own verdict; a
recorded failed check is not described as verified just because conformance.verified
remains true. The record carries no cause or fix order: unless a run field names a causal
link, report failures independently and label any inferred cause, link, or proposed order
as your inference in the sentence that states it. A heading alone does not make that
distinction. One cause is recorded: when a proof’s comparison ran under an assumption
withdrawn for the estate pair, the line names each withdrawal (who withdrew it, when, why)
and how many readings it moved, as licensed readings now unlicensed or readings it made
comparable now indeterminate. Attribute a changed reading to that withdrawal before any
other cause. When a grade records all classification buckets, the comparison counts in
this line use the grade’s classification: drift, spec_licensed and
platform_licensed replace the comparison’s pre-spec unlicensed count. The line
includes the comparison’s errored-read count when recorded. If classification.model_licensed
is nonzero, the line names that subset as derived by the target model rather than
licensed by the platform; the remaining platform-licensed count keeps the latter wording.
When a complete classification
has derived_checked entries, the line also counts those derived tables as not compared
cell by cell (covered by checks). If the grade has no complete classification, it reports
the comparison’s counts instead. The
API reference
defines the field and when it is null.
Give every build you report its own report_this sentence, including when one reply covers
several builds. Read each sentence before your interpretation; when the audience is to
receive the quoted record line, quote it first. A table, list or comparison that names a
build without grounding the report in its sentence is not a substitute. When a grade says
readings are licensed by the spec, report them as licensed rather than as unlicensed drift
or blockers.
When a check you authored fails on a build you believe is correct, report a failed check,
not a build defect. Read the check’s SQL against the mapping clause it cites; repair the
check if it does not measure that clause, or open an adjudication if the result is unclear.
Do not call it a build defect until that review or an adjudication says so. Evidence for an
approver must quote the record’s counts and the obligation ids in the seal you proved
against. A waiver covers drift, not readings the grade already licenses.
Prover run progress
Every run poll carriesprogress, next_step and next, including list rows and terminal
responses. progress has exactly nine keys: phase, phase_basis,
source_message_count, last_activity, write_version, unavailable_reason,
streaming, last_chunk_at and stream_chunk_count.
For a seat-backed run, dispatching means its thread has no message yet and working
means the thread has been written to; working is not a liveness verdict because the
message count is cumulative. Compare last_activity or either counter across polls to
see whether the seat is still writing. A failed read reports phase: "unknown" with
the reason and null counters rather than claiming working; terminal runs report their
own lifecycle status as the phase and do not read the thread. Runs without a seat thread
also publish the same shape with an explanatory unavailable_reason.
The spec-author stall outcome is documented in the author-seat API reference: use error_type: "run_stalled" and its next action to restart after checking committed work. The stall watch compares the thread’s writes with activity reported by the runtime that dispatched the turn; an unreadable runtime view gives no verdict. Before the row becomes terminal, the driver asks that runtime’s hard-stop to stop the turn, retrying refused requests under the configured stop policy. Configure the bound and stop policy in In-product spec author settings.
next_step translates the lifecycle into an action, in words. Live runs say when to poll
again (about 20 seconds); completed runs point to their output, refused and failed runs
explain which summary field to read before submitting again, and cancelled or superseded
runs say that nothing further will be written. No new setting enables this block.
next is the same fact as a literal call — {verb, args, why} — for a caller that would
rather act than parse a sentence. Both are derived by one owner from the status, the run
type and the envelope’s own summary, so they can never name different things. verb is
null, never absent, when no call by this caller moves the work along: a decision a person
records, a permission an administrator grants, a refusal to fix before resubmitting.
A failing grade that read no comparison gets its own Human Review population: each failed
check is a blocker on the grade’s review, where a person can record a ruling or a one-time
exception. The review is explicitly proofless — it says that no comparison against a build
was made — so it can never carry an approval, and no run-level approval is offered for it.
Its next names the proof that creates the comparison beside the grade: prove for a
single sealed spec, or grade over a SET’s spec_hashes with the structural tier. Until
that follow-up reads a comparison, report the failures as reviewed but not approvable.
The finished grade and its get_run poll also hand over this review’s URL and dashboard
path; see the grade tool reference
for the returned fields and null-URL cases.
On a terminal run that produced a comparison, four rules pick it, in order: work the run
left UNMEASURED that one argument would determine (a re-prove carrying row_identity);
then measured findings, which offer the adjudicate call — a proof never opens an
adjudication itself, and a clean comparison’s next says there is nothing to adjudicate;
then a clean comparison that carried no spec, which advises author_spec while stating that
what was proved is that the data values agree and nothing beyond them; then a clean graded
proof, whose remaining act is a person’s. A proof also carries its comparison child’s
verdict counts at summary.comparison_counts so its own envelope can say whether anything
stands.
The three prover_tools answer shapes carry next too — a run handle reads it back off its
envelope, a read names the verb that consumes what it produced, and a refusal names the act
that unblocks it. The same refusal contract applies to the other Prover-family tool
groups, including source_contract_tools and the adjudication, conformance, court,
and ruling tools.
An unidentified refusal means the turn has no signed-in person against whom to check the
permission. This is not a permission denial, so no administrator action is needed. Tell
the user to repeat the act in a turn they start, or in a mission they started; the normal
permission check applies there. A permission refusal instead means an identified person
lacks the permission and may need an administrator to grant it. A supported product-woken
turn can carry its thread owner’s visibility without being that person’s act; see the
identity rules below.
When a Prover action starts a Blueprint, missing Blueprint execute access is a
permission refusal, not a service fault. Ask an administrator to grant the
role execute on that Blueprint before retrying; the
Blueprint mission-start API contract
describes the HTTP denial fields.
Unattended mission visibility
On an unattended mission turn, Prover scopes reads to the person who started the mission when the mission identifies a valid originator. This visibility alone does not make that person the caller or satisfy permission checks. An approval still needs a truthful basis and must be within a goal or mission that person set. If no originator can be established, a scoped read returnsunidentified rather than not_found, which would
imply the object does not exist. If the mission identity cannot be read, Prover returns
unavailable for a scoped read that needs it, so the caller can retry.
Product-woken turns—including mailbox deliveries, run-finished notices, handoff
completions, held-goal nudges, and scheduled runs—can carry the thread owner’s id marked
as borrowed. Prover uses that id for the owner’s visibility and to open their saved
connections, but the turn acts as the agent on behalf of the owner: permission checks use
the agent’s allowlist, and run attribution names the agent and the owner. Visibility alone
does not authorize an approval; an agent’s approval must be part of a goal or mission the
person set and is recorded with that basis. A person’s own prompt and their own held words
are not treated as borrowed turns.
The owner-scoped proposal, bundle, and package-list reads are read_proposal,
read_bundles, and list_packages in the Prover tool reference.
A fault is a re-read, not a terminal answer
refusal.kind: "fault" means the service failed; it does not mean that the system declined
the request, and it does not prove that no work started. Re-read before reporting the act
as finished. The refusal’s next names the same verb and the caller’s same arguments and
identifiers, so make that call to discover whether a standing record already owns the act.
That re-read returns the existing work as reused or reports a conflict instead of starting
a second one. This rule also applies when an exception escaped any Prover-family verb
without a more specific classification: the tool still returns the refusal shape with
kind: "fault", so callers can branch on refusal and next instead of treating a bare
tool error as a completed or terminal run. When the operation is not safe to repeat,
next.verb is null; read the durable record named by the operation before retrying.
When a run or proceeding id was allocated before the failure, the fault names that id
and the read verb to use.
For the retryable unavailable refusal used while a service is starting, see the
service-error mapping.
HTTP 410 Gone maps to not_found, not fault.
Proof admission has one additional hand-off case: if the serving loop stops before
the admission reaches it, nothing was admitted; if it stops after hand-off, the result
is indeterminate. For recovery and the request identity to reuse, follow the
proof endpoint reference.
The Adjudicator exposes the same nine-key block on every response from
POST /api/estate/adjudication/runs/{run_id}/adjudicate. If a call omits round_n, it
joins a proceeding already running for that run under any round; when none is running,
the omitted round uses 0. Name a round to open or read that specific proceeding.
Re-call the endpoint with the same run_id and the response’s round_n to poll the
proceeding that answered; its next_step is specific to that proceeding, and its partial
ruling remains in verdicts against finding_count.
The response also carries started_at; see the API reference
for its round-selection, timestamp, and nullability contracts.
When a grading run opens the proceeding, its snapshot also briefs earlier
verdicts for pair-scoped durable findings in prior_verdicts; see the
fetch_adjudication_materials contract.
The proceeding has no timeout; it ends when the seat submits or orphan reconciliation
closes it. In active mode, if the completed verdicts name no comparison held by the
instance for staging, the proceeding closes as failed instead of remaining open for
retry; its verdicts remain readable and next_step directs the caller to open a new
proceeding. A ledger-refused disposition package also closes the proceeding as failed,
rather than retryable; the submission tool contract
distinguishes it from a failed package write. A fresh proceeding also requires an LLM
provider, while repeating a round
that already has a proceeding is a read; see the API reference
for the response fields. A run detail read can also opt into include_proceedings=true
to list the proceedings opened on that run (addressing only, newest first); use that
pointer because completing a proceeding updates adjudication tables, not the run’s
grade-time summary.
When a proceeding wake carries verdicts, its routing fields and the durable
object_name / column locus are populated from the findings ledger, so a wake and a
poll identify the same finding even though the wake may also include materials.
For a graded proof, the summary includes rounds_used_basis alongside
rounds_used; the basis is always a value, not null. When the request names no round,
the basis says “no round was supplied on the request, so this proof is the first and only
round it can account for”. When the caller names a round, it says “the caller named this
proof’s round, and rounds_used is round_label + 1 in the one 0-based numbering space
(round 0 is the first build)”. The proof also includes ask_level and
ask_level_basis. The builder-facing page uses finding when work is under durable
finding IDs, or ticket when the ticket states the work because the product owns none of
the observed items. A proof delivers no builder page, so its ask_level is null and
the basis explains that absence. An ungraded proof carries neither grade-side key:
spec: null and spec_basis state that the comparison ran without a specification.
For a graded proof, the obligation regression tier is a statement about the series,
not one adjacent round pair. A round above 0 walks the earlier finished grades in the
same series in order, including readable late-completion records for grades that arrived
after their run row was reaped. A FAIL after an earlier PASS opens a demotion, and
that demotion remains in the current tier until a later round grades the obligation
PASS again. The tier therefore lists every demotion still open at round n; each row carries
from_round and to_round so the round that first failed is not lost. A second
consecutive FAIL does not reopen or re-date the row.
Only PASS and FAIL are measurements. An unverified or errored obligation neither
opens nor closes a demotion, and the walk passes through that round. Obligations that
could not be measured, or whose verdict could not be attributed to a sealed structural
item that this tier can follow, are listed in obligation_regressions_unmeasured with a
basis. The latter is still a measured verdict; it is unmeasured only for this
round-over-round structural tier. When no obligation was measured, the tier is
unmeasured (certifies: null) rather than an empty list that could be mistaken for a
clean result. The tier also remains unmeasured when the series walk cannot read the
required earlier rounds.
The grading path also refuses an obligation with an unknown non-null kind instead of
falling through to the keyed comparison contract. A typo therefore cannot become a
determinate PASS; correct the kind and grade again. null remains optional where the
artifact contract permits it.
For an eligible keyed obligation whose source is Foundry and whose source SQL reads only
dataset RIDs, the grade can use their full landed Databricks copies instead of reading
those rows from Foundry. Each RID must have one unambiguous stamped full copy in the
target-side schemas; the copy must not be marked as a pipeline rebuild, and the target
SQL must not read that same table. This is selected during the grade, not
retried only after a Foundry query fails. The result’s source_read identifies each copy
and its warehouse-reported last-altered time, so interpret the verdict against the rows
as landed, not as a fresh read of Foundry.
The same route can serve a source-side invariant whose relation is a dataset RID, but
not when any obligation’s target-side read uses that copy. An invariant graded on the
target stays on the target. A keyed obligation’s grain_probe also runs against copies
when it reads only dataset RIDs covered by the copies already used for source_sql; any
other probe remains on the source. The degeneracy reading follows a copied source_sql
and carries the same source_read evidence. The
API response reference
documents the field shape; the Foundry migration tools guide
explains stamping and adoption.
builder attribution requires both facts: the sealed specification is unchanged by the
series identity, and the bracketing rounds graded different target snapshots. If the
estate did not change, or either round has no target snapshot (for example, an
obligations-only grade), attribution is null and attribution_basis explains why.
The series walk uses the snapshot ids each grade recorded; on a finished grading run,
they may be stored under summary.provenance rather than at the summary’s top level.
The product path has no compiled-spec gating flag, so every demotion row is
demoting: true and includes demoting_basis.
Round 0 is measured-empty only when the grade measured at least one obligation; a
round whose obligations are all unverified/errored, or a spec that declares none, is
unmeasured. A caller that omits the round is not treated as round 0: the grade still
runs, but the obligation tier reports that no series position was named.
When a grade did not measure
The API response reference documents the exact measurement contract: theobligation_verdicts.unverified list names errored or otherwise undecided obligations,
including the declared relation for each obligation so an errored invariant still has
a locus; comparison obligations use null. drift_basis prevents an empty measurement
from becoming a clean certification.
It also explains how spec_hash_basis and projected_spec_hash_basis distinguish a
registered compiled artifact from a run-only projection, including older runs that lack
those fields.
For a declared target mapping, history_not_testable is the companion list for historized
images whose source history was not graded. Each entry names the image and explains whether
the mapping lacked a readable history source or its generated history obligation did not
decide; an empty list means every rendered history check decided, not that a latest-state
table was assumed to contain complete history.
An errored obligation can carry a declared cause: spec_as_written means the
instrument refused the obligation before touching an estate, while instrument means
the grade could not bind or answer it, including a target statement that could not
execute. Read the obligation’s error beside cause; retry unchanged only for a likely
transient failure such as a timeout or dropped connection. If the error names a statement,
relation, or column, correct the relevant connection or catalog, spec statement, or target
before grading again. For keyed checks, a measured missing target column can instead
produce FAIL; see the verification response contract.
An engine that cannot answer the obligation needs another instrument or a ruling. A
missing cause is deliberately not classified from the error text.
When an errored obligation carries errored_sql, its hashes and character counts point
to the sealed source and/or target statements without exposing SQL in the run record;
the compiled-grade API reference
describes how to read those pointers.
A PASS over a measured population of zero rows instead ends as nothing_to_check in
both the obligation’s verdict and status: the check ran, but the data gave it no rows
to decide. coverage.nothing_to_check counts these obligations, and
coverage.items_nothing_to_check counts structural items whose attached checks all ended
this way. They are not passes, failures, errors, or unmeasured checks, and they do not
confirm the relations they cover. When every declared check has this ending, the grade
is not_verified and its headline explains that no check confirms the target; empty
checks alongside other outcomes are called out without counting for or against the claim.
For a seal with a recorded clause_gate, the grade lists unchecked mapping clauses only
from the clauses that gate counted. If a commissioned document had nothing to count,
clauses_not_checked is empty: a ledger entry cannot make a clause number supplied by the
author into a clause of that document. This does not change the reading when no document
was commissioned.
An unchecked mapping clause can still be linked to a structural item. When its ledger
entry’s refs name item ids, the grade says the clause is covered by those items and gives
their verdicts; those items do not become sealed checks for the clause. These links appear
as carried_by_items in the entry under obligation_verdicts.clauses_not_checked, with
each item’s item_id, verdict, and basis. If there are no ledger refs, an exact item id
mentioned in the clause text or seal note instead appears in items_its_note_names; this is
reported only as an item the seal note names, not as grade-asserted coverage. The headline
and report_this give the linkage and item verdicts for the clauses they list; see the
spec-author tool guide
for how to record structural refs.
Each compiled grade also carries a degeneracy reading by obligation. measured means
the probe read the obligation’s expected source side and checked its three known
degeneracies (empty, all-NULL, and all-zero); errored means that read was attempted
but refused or failed; unmeasured means the probe did not run for that obligation or
could not open the source. A measured reading with no findings is not evidence that the
obligation can fail — it only says that none of those three degeneracies was observed.
If an obligation is FAIL but its measured expected source side is empty, the
grade reports it as unverified: the comparison shows target rows without establishing that
the build is wrong, because the check as written has no source rows to compare.
For a violation-count measure, zero violations over rows that exist is the check’s
passing claim rather than an all-zero degeneracy: the grade runs an additional read-only
population count and includes the number of rows counted over in the basis. Only a count
over no rows remains degenerate. Other all-zero measures retain the all-zero finding.
Committed leans now explain rival failures in the grade summary.
Drift findings declare their coordinate
In a completed conformance grade, eachdrift_finding discrepancy declares its join
coordinate in comparison, object_name, and column. comparison names the ledger’s
comparison, object_name names the object, and column is the column name or null for
an object-grain difference. Join or group drift findings with these fields; ref and
evidence remain the addressing and human-readable forms, respectively, and should not
be parsed to recover the coordinate. Older persisted summaries may omit the fields, so a
read of those summaries retains the legacy fallback rather than inventing coordinates.
When a discrepancy carries a non-null bucket, treat it as a lean, not as a ruling
or a punch-list placement. auto: true means a deterministic rule supplied the lean;
auto: false means it came from a judge or that no deterministic rule supplied one.
Read placement for where a finding was actually put and is_lean for whether an
opinion exists. A null bucket means the adjudicator must decide without a lean.
The grade also discloses an incoherent obligation-coverage block when its counters do
not close; do not read a floored zero remainder as proof that every obligation was
accounted for.
The stored grade is terminal, but a later ledger ruling can still change the placement
shown by a run read. For a grade read with a row-bearing shape, Genesis joins ruled
coordinates to the discrepancy’s comparison, object_name, and column; it fills
placement and placement_label only when every ruling for that coordinate agrees.
An unruled coordinate or conflicting rulings remain unplaced and therefore still count
as awaiting adjudication. The served awaiting_adjudication total is recomputed from
those returned rows, while summary.adjudication.buckets remains the grade-time value.
An envelope-only read has no discrepancy rows and does not perform this ruling lookup.
When the named spec is no longer reachable
Run envelopes and proof rows also exposespec_hash_resolvable and
spec_hash_resolvable_basis. These are read-time checks against the compiled-spec store
on the instance serving the response; they do not rewrite the stored spec_hash. A
reader can use them to tell whether a completed grade can still be fetched for
re-verification, rather than treating every status: succeeded run as reachable.
spec_hash_resolvable is true with a basis beginning registered: when this instance
holds the compiled spec named by the run. It is false when the store was read and the
artifact is absent. The corresponding basis begins artifact_absent: when the run said
it graded a registered compiled artifact but this instance does not hold it;
projection_seal_pre_contract: identifies a grade written before the spec_hash
contract, whose hash was a per-run projection seal that was never registered;
direct_envelope_seal: identifies a direct grade whose hash is the sealed envelope
itself; and unattributed_hash: means the record names a hash but does not say what it
represents.
The value is null when no measurement was made. Its basis is the exact sentence
this run names no spec_hash, so there is no artifact to resolve when the run names no
hash, or begins this response did not read the compiled-spec store when the response
did not read the store, including a GET /api/estate/runs/{run_id}?shape=legacy poll.
The spec_hash_resolvable_basis field is always present on the envelope, so callers do
not need to infer whether an omitted field means “not applicable” or “not measured.”
Where a proof cannot measure one of the values it reports about itself, it says so
in place rather than leaving the value out: the field is there carrying no value,
beside a short basis saying why, and naming the record the value would have come
from. A field that simply vanished would be indistinguishable from a server too old to
report it, and a reader cannot act on that difference.
The spec-author seat
A specification is mechanized by an agent in a seat: one thread, read-only access to the estate, and a constitution pinned by name, version and content hash. The tools refuse to run when that pin is not in force, and the seal records it — which is what lets a reviewer say, months later, which doctrine a specification was written under. The seat is listed in your agents as Prover Spec Registrar, beside Prover Adjudicator and Prover Consult. Its agent ID isspec-author, which is what the
PROVER_CANARY_SPEC_BOT setting and its sealed specifications’ provenance name. It
registers a specification a person wrote; it does not invent one.
The open interpretation policy and its Prover Spec Registrar (open policy) bot
(spec-author-open) are retired: lean is the only policy, a run that names open is
refused, and startup removes the spec-author-open bot row while keeping its threads and
history. A specification sealed under open stays readable and is repaired under lean.
New seat runs use Registrar authoring tooling by default. For per-run and deployment opt-outs,
phase checkpoint snapshots, skip requirements and run-end cleanup, see the
Registrar tool guide.
For the polling payload, see the Genesis API reference.
The constitution may be an ordered set of files rather than one file. The seat must read
every pinned file in order before sealing; finalization verifies the files actually served
to that thread. See Spec-author identity and constitution
for the current file order, refusal behavior, and v9.25’s source-side-only R7 boundary.
For constitution v9.27’s derived-build and carried-image seal rules, see the
seal findings and registration fields.
Constitution v9.28 encodes a “when X, then Y” rule as a violation count over the target
(rows where X holds and Y does not, expected 0), not as a membership; see
Spec-author identity and constitution.
Constitution v9.29 lets the seat seal partially: clauses it cannot prove yet are sealed as
open, with a reason, a remedy and the evidence, and the seat run reads sealed_partial; a
follow-up names the partial seal as repair_of to add them; see
Spec-author identity and constitution.
Constitution v9.30 stops the seat asking what a migration already answers: preserve-the-source
properties (NULL counts, empty string vs NULL, whole-row multisets, types, keys, value domains)
are adopted as migration defaults and checked, a question about what the source holds is
measured, and only an intended deviation is put to a person as an open clause with a
recommended answer that does not block the seal; see
Spec-author identity and constitution.
Constitution v9.31 adopts every migration default silently, the row count per key included:
if the answer would be the same for every customer, it is not a question. What does reach a
person (owner or operator) is a choice only they can make, in the business terms of their own
data, with what each choice costs and a recommended answer.
Questions the seat withholds as migration defaults remain recorded separately from the questions
sent to the owner; the author-seat API response
documents that field.
Constitution v9.32 asks every height, key or grain check (a row count, a distinct-key count,
a violation count, a total) to name the table it measures, through owning_relation or a
linked structural item; registration refuses one that names neither, and a check whose only
reading of that table states a typed number is refused as measuring nothing.
Constitution v9.34 requires a fresh Registrar round to declare each target-mapping image
column listed in metadata_columns with a column structural item, including columns with no
source input. An undeclared column prevents the spec from sealing; see the
finalize_spec refusal details
for the accepted declaration loci and repair guidance.
The v9.5 constitution also requires collection-valued checks to state the result for both
empty and NULL collections on both sides; see the spec-author tool reference
for the normalization rule. Target-engine preparation only compiles the target expression,
so it does not replace that semantic check.
When the seat registers a target mapping, it probes every readable hub key even if another
hub’s probe fails; the refusal names all failed probes and preserves findings from probes
that completed. See the spec-author tool reference
for the registration contract.
Conversation-level mapping continuity and its early refusal path are covered in the
author_spec contract.
The seat applies the same proposer-owned undeclared_input seal refusal when an input scope
does not agree with target_model; see the finalization refusal details
for the mapping requirements and target-only input exception. When no mapping was proposed
for a target built from other tables, it returns the same unmapped_reshape refusal instead
of sealing; the finalization refusal details
describe the proposer response.
When no mapping was proposed for a target built from other tables, it returns the same
unmapped_reshape refusal instead of sealing; the finalization refusal details
describe the proposer response.
When an unsided invariant names a relation the declared target model builds, the seat’s
registration rules may infer invariant_side: "target" from measured source absence;
see the obligation registration contract
for the inference receipt and the ambiguity refusal when both estates hold the relation.
If registration cannot establish the side and leaves the invariant source-graded, see the
finalize_spec contract for the
seal-time refusal when its build-output relation is absent from the source.
For a historized image, the seat asks where the source keeps its per-batch history and
expects that relation in the mapping’s history declaration. The mapping renders its
row-membership check as well as the history check; when no source history is declared, the
resulting grade names the image in history_not_testable instead of treating a latest-state
snapshot as proof of history. See Declared target mappings and Data Vault shapes
for the declaration shape and grading rule.
Mapping registration also checks declared references against their referenced source
columns. When a registered mapping splits a source object, register_scope refuses a same
expectation immediately—even if an image keeps the object’s name—so scope each image as
new; see the register_target_model contract
and finalization refusal details.
Finalization also refuses carried_column_added when an add_column item names a column the
mapping carries into a differently named image, carried_column_item for any other column
item on such a column, excluded_but_delivered when the scope excludes an object the mapping
delivers, unassessed_but_assessed when the spec scope, structural items, or obligations
name a table the mapping leaves unassessed, unassessed_without_scope when unassessed tables have no spec scope, and
invariant_grades_nothing for an invariant with no constraint the grade counts; see the
same finalization refusal details.
Successful seals can also carry non-blocking review_findings for contradictory live
clarifications or uncovered must_match structural items; see the
finalize_spec tool reference
for their conditions and how to act on them.
The seat behaves like every other trigger: it returns a handle at once, accepts the same
bounded wait, and is watched at the same address as everything else. The terminal response
contract is in the author-seat API reference.
When an HTTP caller resubmits a prior seat run, it must name that run with resubmission_of;
unlike a same-conversation resubmission, HTTP does not infer a mapping to carry. See the
author-seat request fields.
For a connection serving both estates as separate catalogs, see the
author-seat API reference
and author_spec tool contract
for the source_catalog and target_catalog request fields.
Seat queries: see _query_database.
The constitution states what the diff already covers, so the seat writes only what is
beyond it. Every proof runs the system diff first, and it measures object presence,
column presence, types, row counts with row identity, value distributions and keys
mechanically on both estates. Restating any of that as an obligation doubles a finding,
and a hand-written measurement frozen at authoring time can contradict the diff’s own at
proof time. What is left is what only judgment finds: business rules, semantic
invariants, cross-table consistency, derived-value rules — plus anything the ticket states
as an absolute, because the diff compares the two estates and can never evaluate a
figure, type or domain the ticket names on its own. And a comparison the diff could not take
is not one it passed: it skips wherever either side is unmeasurable, so where it abstained
only an obligation in the specification delivers a verdict.
When several specifications are graded as one set, a cross-table check can use
owning_relation to attribute the check to the one member that owns the relation it names;
the full field contract and fallback behavior are in the spec-author tool reference.
A one-line ticket is a valid brief. “Migrate the SALES database to the target
system as-is; the data values must match” pins no output relation, no column, no derivation and
no domain, so the seat seals the smallest specification that carries a row-set claim and
the diff carries everything else. That is the right answer for a lift-and-shift; a ticket
that states a rule, a derivation, a domain or a reshape gets a correspondingly larger
specification.
Membership root-axis defaults and the registration receipt are documented in the
register_obligation contract.
For a TIME target column ratified for STRING HH:mm:ss storage, the seat must declare
the source column’s form when registering its value binding; it does not infer the form
from the values. See the register_time_value_binding reference
for the accepted forms, unresolved 000000 behavior, SQLite text-encoding support, and
how unsupported-engine refusals are routed.
A repair round hands the seat nothing. When a grade or a review finds something
wrong with a specification, the seat re-authors it — and it is not given the prior
specification in its brief, nor can it reach the sealed file. It loads that specification
through its own tools, edits what the findings actually name, and re-seals. Most untouched
content carries into the new seal unchanged, and the new seal records the one it repaired,
so the chain back to round 0 stays readable. A prior NOT APPLICABLE clause may instead
need grounding again; see the load_prior_spec response.
See the author_spec tooling guidance.
load_prior_spec reports the inherited setting.
A seal made under the retired open policy is repaired under lean; the repair run
records that in seat_settings_inherited.
Classic tooling is retained only for repairing a classic-sealed spec: a classic commission
must name that seal as repair_of, or it is refused at submit and nothing starts. Any repair
may name its prior as repair_of: when it names no catalogs, the seat then reads in the
prior’s catalogs from its first query rather than only once load_prior_spec has run. See the author_spec tool reference
for the per-run override, and the load_prior_spec response
for inherited-setting details. On a classic repair, a commissioned owner clarification can
rule out a carried check through a deletion amendment on finalize_spec; see the
finalize_spec repair guidance.
If load_prior_spec cannot read the seat run, it refuses to seed; follow the retry and
commissioning guidance in the load_prior_spec reference
before continuing.
A repair commissioned without either catalog can inherit it from the prior when the
corresponding source or target connection matches. A chat or CLI repair without a seat run
also inherits the prior’s recorded connection and, when it remains bound there, its catalog
placement; if that prior recorded no connection, its lineage is followed to the nearest
ancestor that did. See the load_prior_spec response
for the repair binding behavior.
When it re-registers a seeded declaration unchanged, the tool preserves that sealed shape
instead of refusing it for a newly introduced conditional rule; changing a conditional field
still invokes validation. See the spec-author tool reference for the exact field-level contract.
That contract also refuses SQL whose NOT IN subquery can yield NULL; use
the register_obligation guidance
for the affected fields and safe rewrites.
The repair-round tool reference documents the fixed prior-grade reading returned by
load_prior_spec, including obligations whose latest grade could not decide them. The
tool checks for registered draft work before paying for that grade and provenance read;
an occupied draft is refused without those reads, while a successful seed records one
fixed grade block for the round.
The seal also records evidence that each obligation source relation was observed
during authoring. That evidence is not tied to one bind mechanism: a resolution
probe, registered query transport, catalog read, or executed sample can provide
the receipt. A repair round carries the prior seal’s evidence for source relations
it does not introduce, while a newly introduced source relation must be observed
before sealing. The tool-level receipt fields and refusal behavior are documented
in spec-author tools — relation observation evidence.
The receipt’s connection must also match the estate the seat was commissioned against;
otherwise the seal refuses a spec re-anchored on a copy unless the operator explicitly
declares the substitute source and reason with source_estate_basis. See the
author_spec tool documentation
for the parameter shape and caller rule. The sealed provenance also distinguishes
surface: "seat" from surface: "tool", so a specification authored by direct tool
calls is not mistaken for one written under the seat’s constitution.
The seat can also receive a caller-declared asset inventory. Each handed-over asset must
be labelled canonical or hypothetical with the caller’s basis; the seat does not infer
or correct provenance. It reports that inventory before deriving obligations. A
hypothetical asset produces a findings pass and stops before sealing, so the caller can
resolve those findings and submit a second run whose assets are all canonical. A run
with no separately declared assets remains the valid one-line-ticket case. The request
and response fields are documented in the author-seat API reference.
An asset may also carry the document itself, inline, as a file in a local bot-git repository,
or as a file attached to the current chat. For a chat attachment, pass the File ID or Git
Path shown by its attachment notice. When the notice spells the attachment as a repository
asset in uploads, omit ref only when no local bot-git repository named uploads exists;
when that local repository exists, supply its ref. See the
author_spec tool reference.
The submitting user must be allowed to open the conversation that contains an
attached upload or a file under the shared uploads repository. Otherwise, the
asset is refused before its bytes are read and the authoring run does not start.
Genesis resolves repository and upload files at submission,
stores each document beside
the run, and the seat reads it in 50,000-character pages with read_spec_asset rather than
working from a caller’s transcription. Numbered items and table rows in those documents are
clauses the seal must account for; asset clause keys are namespaced as <asset>#<key>. The
intake and seal expose the source, character count, SHA-256, and storage metadata, not
the document body. The seat’s limits and unreadable-asset refusal are defined in the
spec-author tool reference.
The caller may also pass clarification record ids for decisions the ticket leaves open.
Use list_clarifications when the id is not known; it lists the estate’s rulings, review
state, and citing sealed specifications. The seat accepts only records belonging to the
named estate, and the sealed specification keeps each record’s label and recorded identity.
An agent record also says which signed-in person the conversation was with, or says
unauthenticated when auth was disabled; that does not make the ruling person-ratified.
If the recording agent later withdraws the ruling on the owner’s word, it cannot be cited by
new authoring; see the withdraw_clarification tool.
This is distinct from ticket prose: a
heading that calls a decision customer-ratified does not establish that provenance. The
spec inspector exposes the resulting who_decided view, and the exact recording and
authoring calls are in the Prover toolkit reference.
Open questions and provider faults
When the seat cannot settle a business question by measuring the estate, it returns the question inopen_questions rather than dropping it. A terminal run notification can bring the numbered
questions back to the agent that called author_spec; the run envelope’s next then names
resolve_open_question for the next unresolved number. Resolve each with a recorded
clarification or an explicit reason to proceed without an answer. The spec can be sealed while
questions remain open; its sealed seat view reports how many owner-directed questions the
authoring turn left for resolution and directs the agent to answer or confirm each. The run
envelope’s next continues to track the unresolved question separately. Only after every
question is resolved does the sealed seat hand off to prove; the same resolution state is
visible from read_spec and the Estate API.
A completed authoring run can also offer a true check the seat declined solely because the
ticket states no rule requiring it. This is separate from open_questions: the notification
gives the obligation id and a ready-made question to put to the ticket owner, word for word.
A numeric maximum or minimum is labeled an observed bound, not a stated requirement: the
current data satisfies it, but that alone does not make it a business rule. The offer asks
whether the business requires that bound; it is still offered because only the owner can
decide. If the owner agrees, create a record_clarification record
with the offered statement and a subject, then commission author_spec again with its
returned id in clarification_ids; the new seal carries the check as a stated rule. The rule
belongs to the owner, so do not answer the offer yourself.
A separate terminal notice can list migration defaults the seat offered but did not register;
these are distinct from owner-rule offers. See the read_spec reference
for how they appear in offered_not_adopted and the repair path.
If the model provider drops or stalls the stream during the seat’s turn, the driver keeps the run
alive and retries in the same thread after
estate_char.spec_author.provider_fault_retry_seconds seconds (default 60; 0 retries
immediately). A retry that faults again is retried after twice the previous wait (60, 120,
240 seconds at the defaults), up to estate_char.spec_author.provider_fault_retry_attempts
retries (default 3) and estate_char.spec_author.provider_fault_retry_ceiling_seconds of total
wait (default 900), so a short provider outage does not cost the run. The brief and work
already registered by the seat remain in that thread. A provider fault after the last retry fails
the run with error_type: "provider_fault"; invalid or rejected requests are not retried. See spec-author settings
for the bounds and the exact configuration contract. If limits are lowered mid-run so a
previously recorded retry is no longer allowed, the driver closes the run as a
provider_fault instead of leaving it open for stale-run reconciliation.
The ticket may also state how the change must be built. In that case the author records
those customer words in the optional SUBSTRATE section with register_substrate; it is
sealed for later retrieval but is not an obligation and is not graded. After the build,
the building agent can read that section by spec_hash and submit a labelled statement:
self_certification with anchored: true when the spec declares a substrate, or
substrate_declaration with anchored: false when it declares none. Either record is
explicitly a statement, not a proof, and carries is_proof: false; mechanical substrate
checks, not the statement, are what can later contradict it. See spec-author tools
and the substrate API endpoints.
For transition-contract source characterization, an engine whose inventory is not
available through the database connector is refused before any catalog read; see the
transition_contract_tools documentation
for the refusal semantics.
Do not key a catalog comparison on ordinal_position.
information_schema.columns.ordinal_position is engine-specific: BigQuery numbers
columns from 1 and Databricks from 0. The seal gate refuses an obligation that reads
information_schema.columns on either side without a portable rank and uses
ordinal_position as a key, because a correct column order can otherwise pair each
column with its neighbour on the other engine.
Rank the columns within each relation instead, for example with
ROW_NUMBER() OVER (PARTITION BY table_name ORDER BY ordinal_position), and use that
portable rank as the key. Using ordinal_position only in compare_columns or
ORDER BY does not trigger this refusal; a rank aliased back to ordinal_position is
accepted only when it is partitioned by table_name and ordered by ordinal_position.
What “certifies” means
A proof reports whether it certifies, and always with the reason it earned. There are three, and the middle one is the one worth understanding:- Nothing counted against it. Clean.
- Something was broken and fixed inside the loop. Every row that counted against certification was re-graded as passing, so the proof certifies.
- Something is still open. At least one row that counts against certification was not repaired, and the proof does not certify.
- A tier could not be measured. The proof reports
certifies: nullwith a basis naming the missing record; it does not treat an unreadable tier as clean.
- A regression repaired under the notice turn is a passing row. The builder broke something and fixed it inside the loop, and the row records that the repair was made under the notice it was given. That is the loop working, and recording it as a failure would punish the mechanism that caught it.
- Certification reads both tiers. Regressions are measured over findings and over obligations, and the two are never merged, because an issue and an obligation are different things about different objects. A run that looks clean at one tier can hold the demotion that stopped it certifying at the other.
- A proceeding rule belongs to a durable finding. When a conformance run has no
usable locus, the item-level match is accepted only for one open durable finding;
ambiguous or unmatched checks are refused instead of becoming synthetic finding
keys. See the
adjudicate_conformance_runtool contract for the matching and refusal behavior. - Obligation rows are product measurements. They compare the persisted per-obligation verdict blocks across rounds. The product path does not invent re-grade, notice-turn, or finding links for these rows; those fields remain empty when the product did not perform those actions.
Fail-closed, deliberately. A row that records no re-grade is not read as repaired.
Treating a missing value as “fine” would certify every run written before that field
existed — the one direction a certification rule must never fail in. Nothing on the
product path writes that re-grade yet, so today a proof carrying any such row does
not certify.
Review decisions are not certification
Certification is a reading a run produced about itself. The review decision is a person’s statement about the comparison, and the two are not the same act: a proof that certifies is evidence in front of you, not a signature on your behalf. What an approval attests to and how its authority is recorded are set out in Roles and approvals, including the basis stored when an agent acts for a person.For the agent doing this
The calls, the response shapes and the refusals live with the code, in the Genesis repository underdocs/prover/ — contract-shaped, written for an agent reading before
it acts, and each page states how it was verified. docs/prover/index.md is the map of
that reference. This page never restates the calls. To read the attestation summary
bound to a comparison, use the comparison-attestation API reference.
When an agent walks the remediation findings worklist, use the bounded
GET /api/estate/findings
page contract: pass each response’s next_cursor as cursor until has_more is
false. Evidence is opt-in because it is the large column; request it only when the
caller needs witness values rather than the default slim listing. For supported
distinct-count findings, the witness view can list values held on only one side;
the API reference documents the longest-value
pane’s length-rank pairing and the binary sample rendering. Systemic-family
annotations expose whether their coordinates were persisted or computed for that
read; the API reference defines family_signature_shape on findings and
signature_shape on family rollups. The distinction is operational only: it does not
change the family id or grouping, and no configuration is required.
When preparing a disposition package, enumerate a comparison with the naming-only
finding_keys shape (or the API’s view=keys) instead of loading evidence the caller
will not read. The package response includes the staging-time coverage denominator;
read it back to report how much of the comparison the proposed batch actually covers.
The public review lifecycle permits one open initial package per comparison, so a
second proposal must finish or withdraw the standing package before trying again.
See the propose_finding_disposition_package contract
for the open_package_conflicts warning returned when a staged item disagrees with
another still-open package on the same estate pair.
prove.md
The one trigger: what to send with and without a specification, the children a
proof names, every status and what to do about it, and the authority a graded
proof requires.
run-envelope.md
The one poll route, the status vocabulary, the provenance block, the bounded wait,
and the loop keys a proof owns — certification, rounds, regressions and counts.
spec-author-seat.md
The seat: what its submit takes, the two escalation modes, what the seal records —
the constitution pin and the chain back to round 0 — and how a repair round reaches
the prior specification without being handed it.
Next
- Overview — what the Prover measures and how its six components fit together.
- How a run works — statuses, provenance, and where to watch.
- Roles and approvals — what lands in front of you and what each button attests to.

