> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genesiscomputing.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Additional Tool Groups

> Reference for the tool groups not previously covered in the main Genesis tool index.

## Overview

This page documents the additional tool groups that extend Genesis beyond the original toolkit index. Use it together with [Tools Overview](/docs/Genbot-Toolkit/Tools-Overview) when you need a complete map of the platform's runtime capabilities.

<img src="https://mintcdn.com/genesiscomputing/PlA8kGWE_2jPvMVf/images/connections_actual.png?fit=max&auto=format&n=PlA8kGWE_2jPvMVf&q=85&s=9a370edb8651217d1c73c4e2934553f2" alt="Actual Genesis Connections page showing multiple integration categories and connector tiles." width="1440" height="1024" data-path="images/connections_actual.png" />

## Server error log inspection

`get_error_logs` reads the curated server error log and groups errors and
exceptions by signature. Use it for the server-wide error gate; use `grep_logs`
when you need pattern-based search through the full application log. Each call
reads the current error log and, when requested or when `since` is supplied,
every retained daily-rotated error log. `max_groups` limits returned groups,
not the files read, so avoid frequent polling.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `since` | string | omitted | Inclusive timezone-aware ISO-8601 boundary for the server-wide error window. Use `observed_at` from the initial unfiltered snapshot; do not advance it during a run. Omit it to include all retained errors. |
| `include_rotated` | boolean | `false` | Also read prior daily-rotated error files. A `since` boundary always includes retained rotated files, even when this is `false`. |
| `max_groups` | integer | `50` | Maximum number of error groups in the response (1–200); does not limit file I/O. |

The response includes `observed_at` (the server's UTC observation time), the
requested `since` value, and `historical_records` counted before the boundary.
Records at or after the inclusive boundary are grouped as current errors;
records with unparseable timestamps remain current errors. Log timestamps with
no timezone offset use the server's local timezone. A missing timezone or a
future `since` value makes the call unsuccessful. When error logging is
disabled, the call also returns `success: false`; treat that as an inability to
verify, not as a pass.

<a id="application-log-search" />

## Application log search

`grep_logs` searches the configured application log with a regular expression.
Use it to investigate a message or identify which mission produced a logged
error; it does not replace `get_error_logs` for the server-wide grouped error
gate. Searches with `since` scan complete logical records in the selected
application log files, including retained rotated files when requested. They can
read large logs, so keep patterns specific and avoid frequent broad searches.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `pattern` | string | required | Regular expression matched against log content. |
| `context_lines` | integer | `1` | Lines of context before and after a match when `since` is omitted (0–10). |
| `case_insensitive` | boolean | `true` | Match without regard to case. |
| `max_results` | integer | `25` | Maximum matches returned (1–100). |
| `log_level` | string | omitted | Optional filter: `ERROR`, `WARNING`, `INFO`, or `DEBUG`. |
| `include_rotated` | boolean | `false` | Also search retained rotated application log files. |
| `since` | string | omitted | Inclusive ISO-8601 timestamp with a timezone offset; must not be later than now. Enables complete-record window search. |

Without `since`, matching is line-based and the response includes `success`,
`count`, and formatted `verbatim_output` with the requested context. With
`since`, the pattern is matched against each complete record, including
continuation/traceback lines and decoded JSON `message` and `exception` fields.
Matches are returned oldest first with `record_timestamp`, `record_text`,
`thread_id`, `parent_thread_id`, `line_number`, and `content`; the response also
includes `since`, `files`, `historical_records`, `unknown_timestamp_records`,
`truncated`, and `window_complete`. The timestamp and identities belong to the
matched record itself, not a neighboring record.

`window_complete` is false when selected records have unknown timestamps or the
search results/output were truncated; such a result cannot prove that no match
exists. An invalid or unreadable search returns `success: false`. For example,
search the current and rotated logs from a captured invocation boundary:

```text theme={null}
grep_logs(
  pattern="MISSION_STARTED project=project-123 thread=thread-456",
  since="2026-10-12T14:30:00+00:00",
  include_rotated=true,
  max_results=100,
)
```

<a id="action-review-tools" />

## `action_review_tools`

Read the current human's Action Review queue in any lifecycle state: governed
actions awaiting review, as well as actions already approved, authorized,
executed, rejected, denied by policy or expired. Each row includes when it was
decided and whether a person or tenant policy authorized it. The caller must
have the `approve_agent_action` permission and pass the human-approval identity
gate. For Snowflake's account-classification limits, see
[Roles and Approvals](/docs/Genesis-Prover/Roles-And-Approvals#who-can-approve).
For how a request's decision reaches its originating agent, see the [Action
Review decision hand-back](/docs/Genesis-API/API-Reference#decision-hand-back-to-the-agent).

### `list_action_reviews`

List up to 25 visible proposals for the current human reviewer. `user_id` and
`bot_id` are implicit from the agent context, so the common call takes no
arguments and returns the `pending_review` queue.

Pass the optional string `status` to read any other lifecycle state —
`authorized`, `claimed`, `executed`, `not_applied`, `reconciliation_required`,
`rejected`, `policy_denied`, `expired` or `invalidated`. It defaults to
`pending_review`. A non-string value or a value outside that vocabulary is
refused rather than silently treated as the default.

`not_applied` means the handler or provider proved that the action was refused
before any write was applied. `reconciliation_required` means the action may
have applied; do not retry it. For execution details and a captured provider
error, inspect the proposal through the [Action Review API](/docs/Genesis-API/API-Reference#action-review-response-fields).

```text theme={null}
list_action_reviews()
list_action_reviews(status="authorized")
```

The response includes:

| Field | Type | Description |
| - | - | - |
| `success` | boolean | `true` when the reviewer-scoped lookup runs; `false` when identity, permission, or lookup validation fails. |
| `proposals` | array | Display-only rows with `proposal_id`, `action_type`, `title`, `summary`, `status`, `admission_outcome`, `authorization_basis`, `created_at`, `expires_at`, and `decided_at`. |
| `total_count` | integer | Number of visible rows found in the bounded snapshot. |
| `truncated` | boolean | Whether the page limit, the bounded scan, or the reviewer-scope checks left the result incomplete. |
| `incomplete_reason` | string or null | `scan_ceiling`, `probe_budget`, `probe_failure`, `handler_unavailable`, or `row_unreadable` when the result is incomplete; otherwise `null`. Only one reason is reported. |
| `row_limit_reached` | boolean | Whether the tool's 25-row page limit prevented it from returning every visible row. This can be `true` alongside another `incomplete_reason`. |

If `truncated` is `true`, tell the user that the list may be incomplete.
The page limit is not an `incomplete_reason`: compare `total_count` with the
number of returned `proposals` to detect that the page contains only the first
page, then point the user to the Action Review page for the remainder. Never
count, total or summarise the returned rows as though they were the whole set.
A `probe_failure` means Genesis could not determine reviewer access for one or
more proposals; suggest retrying rather than treating those proposals as hidden
permanently. A `handler_unavailable` means no handler is registered for an
action type in this deployment, and `row_unreadable` means a proposal's stored
request is malformed. For either reason, tell the user that some items were
omitted and cannot be acted on here; do not suggest retrying because neither is
transient. Incomplete reasons take precedence in this order:
`probe_failure`, `probe_budget`, `handler_unavailable`, `row_unreadable`, then
`scan_ceiling`.

Read `authorization_basis` before describing anything as approved. A
`policy_allow` basis means tenant policy admitted the action automatically and
**no person reviewed it**; `human_approval` means the action passed the
human-approval identity gate, but does not prove a person was present. A row
with no basis was never granted at all.

Use `salesforce_connector` or `hubspot_connector` for CRM merge preview and
execution, not this listing tool.

### `show_action_review`

Put an approve/reject card for one pending proposal into the current
conversation. Use this when an authenticated human signals that they want to
decide a proposal, or immediately after telling them about a pending proposal.
The card lets the human decide in the conversation; the agent cannot approve
on the human's behalf.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `proposal_id` | string | required | The `ap_`-prefixed Action Review proposal ID returned by `list_action_reviews`. |
| `user_id` | string | implicit | Authenticated human identity from the agent context. |
| `bot_id` | string | implicit | Bot identity from the agent context. |
| `thread_id` | string | implicit | Current conversation where the card is delivered. The tool only works inside a thread. |

```text theme={null}
show_action_review(proposal_id="ap_123")
```

The proposal must be pending review and visible to the current reviewer. A
missing or unauthorized proposal is reported as not found, without revealing
whether it exists for another reviewer. If the proposal is no longer pending,
the tool returns `success: true`, `card_sent: false`, its `status`, and its
`authorization_basis`; report that outcome instead of retrying. Use the basis
semantics described for `list_action_reviews` above when explaining the result.

On successful delivery, the response contains `success: true`,
`card_sent: true`, and the proposal's `proposal_id`, `action_type`, and `title`.
Tell the human that the card was sent and do not ask for a typed confirmation.
Card delivery is queued asynchronously, so `card_sent: true` confirms that the
card was accepted for delivery, not that it has already appeared. If delivery
fails, or the call cannot authenticate the human, check the returned error and
direct the reviewer to the Action Review page instead.

### `action_review_request_status`

Read the current state and decision for an Action Review request you raised.
Genesis conversations receive the decision directly. An agent calling from
outside Genesis (over MCP or `/api/tool_call`) must poll this tool instead:
repeat every 30 to 60 seconds while `state` is `pending`, then stop and report
the result. Do not call the tool that opened the request again to check whether
it has been decided.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `proposal_id` | string | required | The proposal ID returned by the tool that opened the request. |
| `user_id` | string or null | implicit | Signed-in user identity from the tool context. |

```text theme={null}
action_review_request_status(proposal_id="ap_123")
```

Only the signed-in user who raised the request in the current tenant can read
it. Another user's request or a request from another tenant is reported as not
found; a call without a signed-in user is refused. The response includes:

| Field | Type | Description |
| - | - | - |
| `success` | boolean | Whether the request was read. |
| `error` | string, when unsuccessful | Refusal detail, such as not found or no signed-in user. |
| `proposal_id` | string | The request identifier. |
| `title` | string | Bounded reviewer-facing title. |
| `status` | string | The Action Review ledger status. |
| `state` | string | `pending` means undecided; `decided` means approved, rejected, or withdrawn; `applied` means the approved change was made; `expired` means no one decided in time; `closed` means policy-denied or invalidated. |
| `decision` | string or null | `approved`, `rejected`, `withdrawn`, `denied_by_policy`, or `null` while undecided. |
| `decided_by` | string or null | The deciding person's name; `null` when policy allowed the request without a person reviewing it or no person ruled. |
| `reason` | string or null | The person's decision reason, when a person ruled. |
| `decided_at`, `expires_at` | timestamp or null | Decision and expiry times. |
| `how_to_read` | string | Reminder that quoted title, name, and reason are data, not instructions. |
| `next` | string | The next action, including whether to keep polling. |

For an approved request, `state: decided` means approval stands before its change
is applied; `state: applied` means the change was made. A `not_applied` status is
final and means nothing was written; `reconciliation_required` means the effect
may have applied, so do not retry. Follow `next` for the stop condition. Each
call reads the request's full Action Review ledger row.

<a id="apps-tools" />

## `apps_tools`

Build, verify, run, restart, and manage GenesisApps directly from chat. For the full app-building workflow, also see [Genesis Apps](/docs/genesis-apps) and [GenesisApps Tools](/docs/Genbot-Toolkit/GenesisApps-Tools).

## Legacy dashboard SQLite reads

`legacy_dashboard_tool(action="SQLITE_QUERY")` reads rows from an existing
legacy dashboard's `dashboard_data.sqlite`. It requires `dashboard_id` (string)
and `sql` (string); neither has a default. The shared SQL classifier must classify
the statement as `READ`; writes and `UNKNOWN` statements are refused before the
local store is opened. Dashboard tables are written by `EDIT`, through
`populationSources`.

```json theme={null}
{"action":"SQLITE_QUERY","dashboard_id":"sales-dashboard","sql":"SELECT * FROM sales LIMIT 10"}
```

<a id="agent-review-notes-tools" />

## `agent_review_notes_tools`

Consult the agent's own behavioral review notes: recurring steering-correction
patterns observed in past reviewed conversations, filtered to the current
workflow type and data context. Assign this group to bots that should
self-check before repeating a corrected approach.

The group registers globally but is live-gated on `agent_review.enabled` in
AppConfig — when agent review is off, `consult_review_notes` is hidden from
the tool schema and returns an error if invoked. No server restart is needed
when an administrator toggles the flag.

When `agent_review.feedback_to_agents.enabled` is `true`, Genesis also injects
the same filtered **AGENT REVIEW NOTES** block into prompts automatically.
Use `consult_review_notes` as the documented fallback when injection is off
or when the agent wants to re-check mid-thread.

### `consult_review_notes`

Fetch behavioral review notes relevant to the current conversation. Returns
only steering guidance — never domain facts about data or SQL.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Derived from the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

Returns a dict with:

| Field | Type | Description |
| - | - | - |
| `success` | boolean | `true` when the lookup ran. `false` only when agent review is disabled or the lookup errored. |
| `notes` | string | The filtered **AGENT REVIEW NOTES** block. An empty string means no adopted or candidate steering patterns match this thread's workflow type and data context — proceed normally. |
| `error` | string | Present only on failure — why the lookup was refused or failed. |

Unlike `search_data_context` and `find_past_queries`, this tool returns
behavioral guidance about how the agent should work, not facts about the
data or prior SQL. On an empty result or failure, fall back to those
data-context tools; do not retry this one in a loop.

Example:

```text theme={null}
consult_review_notes()
```

### `propose_learning_adoption`

Propose adopting a mined learning candidate as a team learning. Use this when
the user asks to keep, promote, or make a recurring correction permanent. The
candidate must have been mined for the current bot, and the caller needs the
`manage_agent_learning` permission. The tool uses the candidate's one Action
Review item: an existing pending or in-flight item is returned instead of
creating a duplicate, and a person's declined decision is not replaced by a
new proposal. If the prior item expired, was invalidated, was not applied, or
was denied by policy, a later call can mint a fresh Action Review item. A
policy-allowed proposal can be adopted immediately; otherwise it waits for a
person in Action Review.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `candidate_id` | string | required | Identifier of the mined learning candidate from the review notes or Agent Learning queue. |
| `bot_id` | string | implicit | Current bot identity from the agent context. |
| `thread_id` | string | implicit | Current conversation thread; used when an Action Review card is delivered. |
| `user_id` | string | implicit | Current user identity for permission and reviewer attribution. |

The result includes `success`, `error` on failure, and `action_review` with the
proposal ID, action type, admission result, and status. A successful result
also includes the adopted candidate result (`candidate_id`, `status`,
`statement_id`, and `adoption_id`). A pending result sets `pending_review: true`
and means nothing has changed yet; do not call the tool again for the same
candidate. A policy refusal sets `denied_by_policy: true`. If a person has
already rejected or revoked this adoption, the result sets
`declined_in_action_review: true`; that decision stands and the candidate
should not be proposed again. An uncertain result has Action Review status
`reconciliation_required`; do not retry it, and check the anchor's wiki page
when the candidate was anchored.

Example:

```text theme={null}
propose_learning_adoption(candidate_id="candidate_123")
```

<a id="aws-tools" />

## `aws_tools`

Perform AWS operations such as EC2- and S3-backed workflows from an agent conversation. This group is best suited to teams that already operate workloads in AWS and want agent-assisted cloud operations.

When these tools use a saved AWS connection, Genesis can authenticate with
either `Access Key` credentials or `IAM Role (IRSA / Pod Identity)` from the
running workload. See [Connections](/docs/Setup/Connections) for the exact mode
selection flow and field names.

### `aws_action` access-denied errors

When AWS returns an IAM access-denied error (for example `AccessDenied`,
`UnauthorizedOperation`, or `AccessDeniedException`), `aws_action` enriches the
response with the caller's IAM ARN when it can be resolved from the saved
`credential_name` via STS `get_caller_identity`.

| Response field | Type | Description |
| - | - | - |
| `success` | boolean | `false` |
| `error` | string | AWS error message prefixed with `AWS access denied:` |
| `caller_identity` | string | IAM ARN of the identity that attempted the call |
| `hint` | string | Guidance to grant the missing permission to that IAM role or user |

When `credential_name` is omitted or STS lookup fails, Genesis falls back to
the generic `success: false` response with `error` set to
`AWS operation failed: ...` and no `caller_identity` field.

<Note>
  This enrichment applies to AWS IAM permission failures from boto3. It is
  separate from Genesis RBAC denials, which return
  `Access denied: user or agent does not have permission to view the requested information`.
</Note>

<a id="blueprint-creation" />

## `blueprint_creation`

Turn a successful thread into a reusable blueprint so the same workflow can be launched again with less manual setup.

### `create_blueprint`

Use `create_blueprint` to generate a reusable blueprint from one or more successful threads, inspect an existing blueprint before editing it, and preview or apply targeted working-copy changes. Use `CREATE_BLUEPRINT_FROM_THREADS` for new blueprints from conversations, `PREVIEW_EDIT` to stage an update, and `APPLY_EDIT` to commit a reviewed preview.

<Note>
  `CREATE_BLUEPRINT_FROM_THREADS` runs background analysis through Genesis
  utility LLM calls that request structured JSON output. This path works with
  Claude models on **Snowflake Cortex** and on LiteLLM-backed providers
  (including **LiteLLM Proxy**, **AWS Bedrock**, and **Anthropic**). On Cortex
  Claude, Genesis omits OpenAI's unsupported schema-less `json_object` response
  format and relies on JSON-only prompts with parse retry. On LiteLLM Claude
  routes, Genesis applies the same model-aware `max_tokens` defaults used for
  chat so long blueprint manifests are not truncated mid-generation. Auxiliary
  utility LLM calls raise structured provider failures (`not_configured`,
  `provider_exception`, or `empty_response`) instead of returning provider error
  text as job output. If creation fails with a provider error, verify the
  active chat provider in **Config → AI Providers** and retry
  `CREATE_BLUEPRINT_FROM_THREADS`.
  For output-limit handling during analysis, synthesis, and optimization, see
  [Blueprint Library and Missions](/docs/Blueprint/Blueprint-Library-And-Missions).
</Note>

#### `action="GET_CREATION_STATUS"`

Call this after `CREATE_BLUEPRINT_FROM_THREADS` returns a `job_id`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Use `GET_CREATION_STATUS` to check an in-progress blueprint generation job. |
| `job_id` | string | none | Required. Job ID returned by `CREATE_BLUEPRINT_FROM_THREADS`. |

| Response field | Type | Description |
| - | - | - |
| `status` | string | Current generation stage: `pending`, `analyzing`, `generating`, `optimizing`, `saving`, `complete`, or `error`. |
| `progress` | integer | Percentage complete. |
| `tool_result_status` | string | `running` while generation is still in progress, then `completed` or `failed` when the job finishes. |
| `next_poll_seconds` | integer | Suggested delay before the next call when `tool_result_status` is `running`. |
| `message` | string | Human-readable progress summary while the job is still running. |
| `blueprint_name` | string | Generated blueprint name when creation succeeds. |
| `blueprint_path` | string | Saved blueprint location when creation succeeds. |
| `error_message` | string | Error details when creation fails. |

Example:

```text theme={null}
create_blueprint(action="GET_CREATION_STATUS", job_id="job_xyz789")
```

#### Editing existing blueprints

Call `GET_BLUEPRINT` with `blueprint_name` to inspect the current manifest and
phase structure before building a targeted edit. For existing blueprints,
Genesis uses a preview-first workflow: `PREVIEW_EDIT` stages the change and
returns a `preview_id`, then `APPLY_EDIT` commits that preview after review.
Use structured `edit_operations` whenever the change decomposes cleanly into
specific fields, phases, actions, or exit criteria. Fall back to
`change_description` only when the requested update does not fit those
structured operations cleanly.

<Note>
  `GET_BLUEPRINT` is review-only. It returns the blueprint definition for
  inspection or editing, but it does not create a Mission, enter a phase, or
  authorize manual execution from chat. When the user wants to run a blueprint,
  use `start_blueprint_mission` from
  [Project Manager Tools](/docs/Genbot-Toolkit/Project-Manager-Tools) instead
  of manually following the manifest or `GET_BLUEPRINT_INFO` output.
</Note>

Successful `GET_BLUEPRINT` calls return the manifest plus `source_type`,
`editable`, `read_only`, `execution_guardrail`, and suggested `next_steps` so
callers can branch cleanly into edit-versus-run flows.

#### `action="PREVIEW_EDIT"`

Preview changes to an existing blueprint before applying them.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Use `PREVIEW_EDIT` to stage changes to an existing blueprint. |
| `blueprint_name` | string | none | Required. Target blueprint working copy to edit. |
| `change_description` | string or null | `null` | Optional natural-language change request. Use this only when Genesis must infer an edit that does not decompose cleanly into structured operations. |
| `edit_operations` | `object[]` or null | `null` | Optional structured edit list. Prefer this when you already know the exact phase, field, action, exit criterion, or metadata target. `PREVIEW_EDIT` plans deterministic operations from this list rather than rewriting the manifest. Supported `op` values: `set_blueprint_field`, `append_blueprint_list`, `add_phase`, `remove_phase`, `rename_phase`, `set_phase_field`, `insert_action`, `replace_action`, `remove_action`, `add_exit_criterion`, `replace_exit_criterion`, and `remove_exit_criterion`. |
| `edit_mode` | string or null | `null` | Optional edit strategy. Allowed values: `metadata_only`, `preserve`, or `harden`. |

`PREVIEW_EDIT` requires `blueprint_name` plus either `change_description` or
`edit_operations`.

For phase `exit_criteria` authoring rules, enforced types, and examples, see
[Exit criterion types](/docs/Blueprint/Blueprint-Branching#exit-criterion-types).

<Tip>
  Prefer `edit_operations` when you already know the exact target from
  `GET_BLUEPRINT` or the user's instructions. Targeted operations preserve
  untouched phase fields and avoid natural-language planner drift. If a
  planner-driven `change_description` call fails, retry with explicit
  `edit_operations` instead of editing `blueprint_manifest.yaml` directly with
  `git_action` or file tools.
</Tip>

<Note>
  A blueprint loads from one `blueprint_manifest.yaml` file. Runtime loading
  does not resolve `$ref`, `include`, or other multi-file phase-definition
  patterns, and unknown phase fields are ignored at load time. Keep phases in
  the manifest, and move only supporting prose or examples into companion
  files such as Markdown documents.
</Note>

Common `edit_operations` patterns:

* Use `set_blueprint_field` or `append_blueprint_list` for metadata updates.
* Use `insert_action`, `replace_action`, or `remove_action` for action-level edits.
* Use `set_phase_field` for broad rewrites and include every phase field you
  intend to change.
* Use one `PREVIEW_EDIT` call with multiple operations when you want one
  combined preview.

Example:

```text theme={null}
create_blueprint(
  action="PREVIEW_EDIT",
  blueprint_name="data_vault_build",
  edit_operations=[{
    "op": "insert_action",
    "phase_id": "2",
    "position": "after_action",
    "action_match": "Create models",
    "action": {"action": "Validate row counts"}
  }]
)
```

#### `action="APPLY_EDIT"`

Apply a previously previewed edit.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Use `APPLY_EDIT` to commit a previewed blueprint change. |
| `preview_id` | string | none | Required. Preview ID returned by `PREVIEW_EDIT`. |

<a id="branding-tools" />

## `branding_tools`

Read and update organization branding settings such as colors, logos, and design guidance. This group complements the [Branding](/docs/Setup/Branding) setup page.

<a id="claude-code-tools" />

## `claude_code_tools`

Use Claude Code from Genesis for delegated coding tasks. Workspace admins can
globally allow or block these tools in **Config → Workspace Policies** under
**Tool Permissions → Coding Agent Controls**. See
[Coding Agent Controls](/docs/User-Guide/Coding-Agent-Controls) for the
customer-facing workflow.

These delegation tools are unavailable in Genesis Desktop. For the Desktop
coding-agent workflow, see [Coding Agent Controls](/docs/User-Guide/Coding-Agent-Controls).

The direct `_claude_code` tool is unavailable when the Genesis server runs on
Windows because it drives the CLI through a POSIX pseudo-terminal. Run Genesis
on macOS or Linux to use this tool.

For Claude Code clients using room actions, `room_send` is subject to the
per-sender, per-room limit documented in [Agent rooms endpoints](/docs/Genesis-API/API-Reference#agent-rooms-endpoints).

<a id="codex-code-tools" />

## `codex_code_tools`

Use Codex from Genesis for delegated coding tasks. Workspace admins can
globally allow or block these tools in **Config → Workspace Policies** under
**Tool Permissions → Coding Agent Controls**. See
[Coding Agent Controls](/docs/User-Guide/Coding-Agent-Controls) for the
customer-facing workflow.

<a id="confluence-connector-tools" />

## `confluence_connector_tools`

Search and manage Confluence spaces, pages, and attachments. See [Confluence](/docs/Setup/Confluence) for setup.

When `connection` is omitted, Genesis resolves the effective default `confluence` connection for the current user and bot (**My default**, then **Role default**). Genesis injects `bot_id`, `thread_id`, and `user_id` from the active conversation automatically. **User OAuth (Cloud)** connections act as the requesting user; the caller must be present in the active thread context.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `LIST_SPACES`, `GET_SPACE`, `LIST_PAGES`, `GET_PAGE`, `SEARCH_PAGES`, `CREATE_PAGE`, `UPDATE_PAGE`, `APPEND_TO_PAGE`, `DELETE_PAGE`, `CREATE_SPACE`, `LIST_CHILD_PAGES`, `DOWNLOAD_ATTACHMENTS`, and related Confluence operations. |
| `connection` | string | `null` | Optional saved connection name such as `confluence.shared` or `shared`. Uses the effective default `confluence` connection when omitted. |
| `base_url` | string | `null` | Optional Confluence base URL override when no scoped default applies. |
| `username` | string | `null` | Optional username/email override for basic auth. |
| `password` | string | `null` | Optional password override for basic auth. |
| `pat` | string | `null` | Optional token override. Cloud: API token with `username`/email basic auth. Local/DC: PAT as bearer token. |
| `limit` | integer | `25` | Maximum results for list/search actions (max `200`). |
| `start` | integer | `0` | Pagination offset for list/search actions. |
| `download_dir` | string | `/tmp/genesis_confluence_attachments` | Optional destination for `DOWNLOAD_ATTACHMENTS`. Use a folder below this default directory, or `BOT_GIT:<repo_id>/<folder>` to save into a repository. Other paths and repository `.git` metadata are refused. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `user_id` | string | implicit | Derived from the requesting user context. |
| `thread_id` | string | implicit | Derived from the active thread (reserved for future file/content workflows). |

When the acting user cannot use the resolved connection (for example a
**personal** connection owned by someone else), `confluence_connector` returns
`Success: false` with a `Suggestion` explaining that the failure is a connection
access/permission issue, not invalid credentials. Ask the connection owner to
run the request in-thread, or have an admin with `manage_all_connections` share
the connection.

<a id="connections-action-tools" />

## `connections_action_tools`

Create, inspect, update, test, remove, and resolve defaults for saved external-service connections. It is the agent-facing companion to the Connections setup UI.

### `connections_action`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `HELP`, `LIST_TYPES`, `LIST`, `FIND`, `GET`, `CREATE`, `UPDATE`, `DELETE`, `TEST`, `GET_DEFAULT`, `SET_DEFAULT`, or `CLEAR_DEFAULT`. |
| `connection_type` | string | `null` | Required for `HELP`, `GET`, `CREATE`, `UPDATE`, `DELETE`, `TEST`, `GET_DEFAULT`, `SET_DEFAULT`, and `CLEAR_DEFAULT`. Optional filter for `LIST`. |
| `name` | string | `null` | Required for `GET`, `CREATE`, `UPDATE`, `DELETE`, `TEST`, and `SET_DEFAULT`. |
| `locator_json` | string | `null` | JSON string with connection parameters. Required for `CREATE`, optional for `UPDATE`. |
| `is_default` | boolean | `null` | Deprecated on `CREATE` and `UPDATE`. `true` values are rejected. System/shared default connections are no longer supported. |
| `access_intent` | string | `unspecified` on create | Declared read-vs-modify intent for `CREATE` or `UPDATE`: `unspecified`, `read_only`, or `read_modify`. `read_only` is enforced for SQL that Genesis runs: write-class statements are refused on the connection (not covered: MongoDB connections, the native Snowflake connection and the Snowflake SQL API tools). `read_modify` is an awareness label for agents and the Agent Center badge. Omit on `UPDATE` to keep the existing value. `GET` and `LIST` return the stored value. |
| `default_scope` | string | `user` | Scope parameter accepted by `GET_DEFAULT`, `SET_DEFAULT`, and `CLEAR_DEFAULT`. Use `user` or `role`. `GET_DEFAULT` still returns stored default layers for the type. |
| `role_name` | string | `null` | Role identifier when `default_scope="role"` on `SET_DEFAULT` or `CLEAR_DEFAULT`. |
| `scope` | string | `shared` on CREATE | Connection scope for `CREATE`/`UPDATE`: `personal` (only you) or `shared` (all users). Creating shared connections or changing an existing connection's scope requires `manage_all_connections`. Omit on `UPDATE` to keep the existing value. |
| `personal_credentials` | string | `disabled` | Shared-connection credential policy for `CREATE`/`UPDATE`: `disabled`, `optional`, or `required`. Personal connections do not use a shared policy. The selected authentication mode must expose principal fields for `optional` or `required`; otherwise the request is rejected. |
| `roles_with_access` | string\[] | `null` | RBAC role names allowed to resolve this connection's secret (`CREATE`/`UPDATE`). On `UPDATE` this replaces the full set; pass `[]` to revoke all, or omit to leave bindings untouched. |
| `additional_hosts` | string\[] | `null` | Additional host authorities for `CREATE`/`UPDATE`. Pass hostnames without a scheme, path, query, fragment, or credentials; a connection accepts at most four. Omit on `UPDATE` to keep the existing list. |
| `resource_identifier` | string | `null` | Optional URL, host, or provider text to rank with `LIST`; also accepted by the deprecated `FIND` alias. |
| `resource_type` | string | `null` | Deprecated compatibility type constraint for `FIND`; use `connection_type` with `LIST`. |
| `limit` | integer | `5` | Maximum ranked `LIST` or deprecated `FIND` results to return. |
| `secret_conflict_resolution` | string | `override` | How to handle secret conflicts: `override`, `use_existing`, or `abort`. |
| `bot_id` | string | implicit | Derived from the acting agent context. Used when listing, reading, or testing a connection in that agent's RBAC and access context. |
| `user_id` | string | implicit | Derived from the requesting user context. |

`UPDATE` verifies connectivity before persisting a supplied `locator_json`. A
failed verification leaves the saved connection and its secrets unchanged. The
verification uses the credential that the update will retain: with
`secret_conflict_resolution="use_existing"`, Genesis opens the stored secret;
otherwise it opens the submitted value. Metadata-only updates without a locator
do not perform a connectivity check.

For an MCP connection, `CREATE` and `UPDATE` also make one tool-discovery request
to the server. Their successful response includes `mcp_tools` with `registered`
(boolean), `tool_count` (integer), and `message` (registration message). A failed
registration does not undo the saved connection; startup replay can register its
tools later. See [MCP server connections](/docs/Setup/Connections#mcp-server-connections)
for the connection lifecycle, including deletion.

`TEST` resolves the saved connection using the current `bot_id`, so the result reflects the active agent's RBAC, connection assignment, and secret-access rules instead of a generic backend-only connectivity check.

`GET_DEFAULT` returns scoped-default metadata for one connection type in `data.connection_type`, `data.system_default`, `data.user_default`, `data.role_defaults`, `data.effective_default`, `data.effective_default_source`, `data.matched_roles`, and `data.ambiguous`. `data.system_default` is always `null` (system/shared defaults are no longer supported). `data.effective_default` is the resolved default after user, then role layers only; when no scoped default applies, it is `null`.

`LIST` accepts optional `connection_type`, `resource_identifier`, and `limit` parameters. When `connection_type` is set to a value that is not in the connection registry, the tool returns `success: false` with an `error` message listing valid types — not an empty `data` array. Use `LIST_TYPES` first to discover supported types (including types with no saved connections yet, such as `mssql`).

`LIST` returns only connections usable by the requesting user and active bot. Each `data` entry includes non-secret discovery metadata: `connection_id`, `credential_origin` (`connections_api` or `legacy_db`), `is_user_default`, `is_role_default`, `is_effective_default`, `effective_default_source`, and any `warnings` such as `oauth_authorization_required`, `oauth_grant_expired`, or `egress_pending_approval`. The response also includes `resolution_by_type`, which reports the resolution `state`, selected connection id and source, and any `conflicting_connection_ids` for each returned type. With `resource_identifier`, LIST adds `ranking` without changing the base rows. `ranking.matches` contains native Connections API rows with score, reason, strategy, separate `match_warnings` and `discovery_warnings`, counts, and `unique_exact_connection_id` when exactly one warning-free score-100 match exists.

Connection summaries returned by `LIST`, `GET`, `CREATE`, and `UPDATE` include `connection_id` (the Connections API's `<type>.<name>` identifier) and `canonical_connection_id` (the canonical identifier used to match the same connection across listings).

Connector tools that resolve connections use the same requester-aware checks. If an omitted connection cannot be selected, the tool returns a structured `success: false` response with `error_code`, `resolution_state`, `connection_type`, safe `candidates`, and `retry.tool_parameter`. Retry with the candidate's fully qualified id (for example `linear.team-a`) or ask the user to choose one. An explicit id may also be supplied as the provider-prefixed form or its legacy bare name; an id with a different provider prefix is rejected.

`FIND` is a deprecated one-release compatibility alias for LIST with a resource identifier. It returns the same structured catalog and ranking data and does not open a card, suspend a thread, execute a provider action, or generate a continuation. Agents should use `LIST` and ask an ordinary conversational question for ties, sub-100 matches, or warning-bearing results. A unique warning-free exact match may be used only by a subsequent explicit read-only or idempotent provider call after disclosing the selected connection.

`LIST`, `GET`, and `TEST` apply the same connection-scope and secret-access checks as the Connections API: `LIST` omits connections the active user or bot cannot use, while `GET` and `TEST` return a not-found-style error for inaccessible connections. See [Connections — Personal vs shared](/docs/Setup/Connections#personal-vs-shared-connections) for the visibility and credential rules.

On a successful `CREATE`, `data.owner_user_id` is the owner recorded on the
connection and `data.created_by` is the recorded creator. The response also
includes `attributed_to_another`: `false` when the owner is the signed-in user,
and `null` when the connection names nobody. A connection created without a
signed-in user is displayed as `unattributed`; its internal system principal is
not a person and is never presented as one.

`personal_credentials` controls whether a shared connection may resolve a
user-attributed principal credential. Set it on `CREATE` or `UPDATE`; it is
returned by `GET` and `LIST`. Users bind or unbind their own principal through
the Connections page or the [personal credential endpoints](/docs/Genesis-API/API-Reference#personal-credential-endpoints).
Background operations continue to use the shared/service credential.

<Note>
  `SET_DEFAULT` supports `default_scope="user"` or `role`. `CLEAR_DEFAULT` supports `user` and `role`. Role defaults require `manage_all_connections`, and Genesis only allows them on shared non-legacy connections that the target role can already access. `default_scope="system"` and `is_default=true` on `CREATE`/`UPDATE` are rejected.
</Note>

<Note>
  `connections_action` enforces the PAT-connection gate on `CREATE`, `UPDATE`,
  and `TEST`. If `locator_json` resolves to a PAT-class connection (`auth_type`
  of `pat`, `api_token`, or `api_key`, or an omitted `auth_type` with PAT-style
  fields such as `access_token`), the requesting user must have the matching
  `access_pat_connections_<category>` permission for the target connector
  category (`databases`, `git`, `cloud`, `pipelines`, or `tools`). Otherwise
  the tool returns:
  `Your role does not allow PAT-based tool connections. Use OAuth instead, or ask an admin to enable PAT capability for your role.`
</Note>

<Note>
  `connections_action` applies the same admin-only runtime-identity
  authorization as the Connections API for BigQuery application-default and
  Databricks Lakebase and Iceberg App-identity connections. See
  [Connections — BigQuery](/docs/Setup/Connections#bigquery-connections),
  [Databricks Lakebase connections](/docs/Setup/Connections#databricks-lakebase-connections),
  and [Databricks App lakehouse connections](/docs/Setup/Connections#databricks-app-lakehouse-connections)
  for fields and runtime behavior.
</Note>

In a Databricks App, `LIST_TYPES` omits unavailable authentication modes and
`HELP` skips them, so the agent does not suggest credentials the save would
refuse. This includes host-identity modes unavailable in the App and AWS/MWAA
`assume_role` without bootstrap access keys. The Connections UI instead keeps
these modes visible but disabled with the reason; see [Connection mode chooser](/docs/Setup/Connections#connection-mode-chooser).

<Note>
  On `CREATE`, `UPDATE`, and `DELETE`, pass connection fields as top-level
  parameters (`connection_type`, `name`, `locator_json`, `scope`,
  `roles_with_access`, `access_intent`, `secret_conflict_resolution`). There is
  no nested `updates` object — unknown parameters return
  `Unknown parameter(s) for &lt;action&gt;: ...` so callers can self-correct.
</Note>

Example:

```text theme={null}
connections_action(action="LIST_TYPES")
connections_action(action="LIST", connection_type="jira", resource_identifier="https://acme.atlassian.net/rest/api/3/project")
connections_action(action="HELP", connection_type="github")
connections_action(action="TEST", connection_type="github", name="shared")
connections_action(action="GET_DEFAULT", connection_type="github")
connections_action(action="SET_DEFAULT", connection_type="github", name="work", default_scope="user")
connections_action(action="SET_DEFAULT", connection_type="github", name="platform", default_scope="role", role_name="engineering")
connections_action(action="CLEAR_DEFAULT", connection_type="github", default_scope="user")
connections_action(action="UPDATE", connection_type="confluence", name="team-wiki", scope="shared", roles_with_access=["user"])
```

<a id="dataset-tools" />

## `dataset_tools`

Create, refresh, materialize, and delete datasets that support fast, governed data access for apps and analytical views.

Use `inline_data` only for tiny toy examples or a few hand-authored rows. Genesis caps `inline_data.rows` at `50,000` rows, and those rows still pass through LLM context. For synthetic or other bulk data, generate files first, load them into `workspace_sqlite` with `_load_to_sqlite`, then define the dataset with `source_type="sql"` and `connection_id="workspace_sqlite"`.

### Built-in Cost & Usage cube

Genesis ships a protected system dataset `genesis_cost_usage_cube_v1` and the
`genesis_cost_usage_dashboard` app. The preset materializes three system-metrics
sources:

| Source ID | Table | Purpose |
| - | - | - |
| `cost_usage_cube` | `cost_usage_cube_v1` | Chat, tool, thread, and auxiliary/system LLM cost facts. |
| `users_dim` | `users_dim_v1` | User display-name dimension. |
| `scan_usage` | `scan_usage_v1` | Twin scan LLM spend priced into USD at hourly grain. |

Twin scan rows are read from `SCAN_USAGE_FACTS`, which the background
`twin_scan_cost_sync` job populates on a schedule. Dataset refresh does not run
that sync — it only materializes rows already in the cube store.

The dashboard's **Top Threads by Known Spend** section groups threads by
instance and thread and includes LLM and metered-service spend. It shows
unpriced and unknown-price call counts when pricing counts are complete; known
spend with incomplete pricing is shown as a lower bound, and spend with no
known price is unavailable. The section reads the materialized cost cube, so
new data appears after the next dataset refresh (the preset's default schedule
is `@daily`). See the [API reference for the thread-spend view](/docs/Genesis-API/API-Reference#built-in-genesis_cost_usage_cube_v1)
for its aggregation and fields.

Scan-cost views on the preset:

| View ID | Groups by |
| - | - |
| `scan_cost_by_source_v1` | `source_id` |
| `scan_cost_by_operation_v1` | `operation` |
| `scan_cost_by_model_v1` | `model`, `provider` (non-empty model only) |
| `scan_cost_over_time_v1` | `date_utc` |
| `scan_unpriced_v1` | `source_id`, `model` (rows where `cost_total_usd` is NULL) |

`SUM(cost_total_usd)` ignores NULLs, so unpriceable scan rows stay visible in
token totals without fabricating zero-dollar cost. The dashboard **Scan Cost**
tab renders these views.

### `default_cost_usage_cube_create_tool`

Create or update the built-in Cost & Usage cube preset and return
`dataset.<dataset_id>` connection info plus an `app_binding` for
`genesis_cost_usage_dashboard`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `dataset_id` | string | `genesis_cost_usage_cube_v1` | Stable dataset identifier. |
| `refresh_after_create` | boolean | `true` | Build or refresh the snapshot immediately. |
| `exists_ok` | boolean | `true` | Update an existing definition with the same `dataset_id`. |
| `schedule` | string | `@daily` | Refresh schedule (`@daily`, `cron:<5 fields>`, `interval:<count><unit>`). |
| `max_rows` | integer | `100000` | Row cap for `cost_usage_cube` and `scan_usage` sources. |
| `include_definition` | boolean | `false` | Include full embedded view SQL in the response. |
| `run_as_user_id` | string | none | Optional owner or refresh user id. |

Example:

```text theme={null}
default_cost_usage_cube_create_tool(exists_ok=True)
```

### `dataset_delete_tool`

Delete a dataset, with a confirmation step when the dataset is still bound to one or more apps.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `dataset_id` | string | none | Required. Dataset identifier to delete. |
| `confirm` | boolean | `false` | Re-call with `true` after Genesis reports `requires_confirmation: true` for bound apps. |

Genesis blocks deletion of built-in system datasets. When a dataset is still bound to apps, `dataset_delete_tool` returns `bound_app_count`, `bound_apps`, and a confirmation hint instead of deleting immediately. With durable storage, Genesis removes remote snapshot copies before deleting the dataset record; a failed removal leaves the dataset intact. If an active refresh holds its lock for over 30 seconds, deletion returns a retryable busy error.

Example:

```text theme={null}
dataset_delete_tool(dataset_id="sales_cache")
dataset_delete_tool(dataset_id="sales_cache", confirm=True)
```

<a id="flow-tools" />

## `flow_tools`

Create and manage Genesis Flows: lightweight deterministic SQL and Python workflows that run on demand or on a schedule. Flow runs are not the full chat agent loop; optional Python-step calls to `genesis_flow.llm.ask` route through Genesis model settings and bill like other base LLM usage. For the customer-facing workspace, see [Flows](/docs/User-Guide/Flows).

### `flow_action`

Use this function to create, list, inspect, run, update, delete, schedule, and validate flows.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `CREATE`, `LIST`, `GET`, `GET_VERSIONS`, `GET_VERSION`, `RUN`, `UPDATE`, `REVERT`, `PROMOTE`, `GET_PENDING`, `PROMOTE_PENDING`, `FORK_TO_STANDALONE`, `DELETE`, `SCHEDULE`, `GET_RUN`, `GET_RUNS`, `CANCEL_RUN`, `VALIDATE_RUNNER`, `VALIDATE_DEFINITION`, `REGISTER_MANAGED_SOURCE`, `SYNC_FROM_REPO`, `PUSH_TO_REPO`, `EXPORT_PREVIEW`, or `EXPORT_COMMIT`. Managed-source actions require `manage_flows`; `GET_PENDING` and `PROMOTE_PENDING` require `manage_flows`. |
| `params` | object | none | Required. Action-specific payload. For `CREATE` and `UPDATE`, you can include either `parameters_schema={name:{type, required?, default?}}` or `parameters=...`. `parameters` accepts the same object form or a list of declarations such as `[{name:"n", type:"int", required:true}, {name:"flag", type:"bool", default:"true"}]`; Genesis normalizes either form, applies defaults, rejects missing required inputs, and coerces simple `int` / `float` / `bool` / `string` values at run start. `UPDATE` on a git-backed flow still allows `is_enabled` (pause/resume) but blocks definition changes that would diverge from Git. `FORK_TO_STANDALONE` requires `{flow_id, new_name}` and copies a git-backed flow into a standalone genesis-versioned flow. `REVERT` and `PROMOTE` apply only to genesis-versioned flows. `GET_PENDING` accepts `{pending_id?, source_id?}`: omit `pending_id` to list waiting changes, optionally filtered by source; pass it to preview the pending change, including before/after definitions and dependency status. `PROMOTE_PENDING` accepts `{pending_id, pending_fingerprint, live_fingerprint, enable?}`; pass both fingerprints unchanged from the preview. `enable` is a boolean defaulting to `false` and applies only to a Flow new to this install. Promotion refuses a stale preview or unresolved dependencies without applying the change. If the result is `applied_finishing`, call `PROMOTE_PENDING` again with the same `pending_id` to finish the owed step. For `SCHEDULE`, pass `{flow_id, trigger}` with `trigger={type:'cron', cron:'<cron_expr>', timezone:'<tz>'}`. Genesis also accepts flat shorthand `{flow_id, schedule:'<cron_expr>'}` or `{flow_id, cron:'<cron_expr>'}`; `cron_expression` is accepted as a compatibility alias. In the flat form, `timezone` is optional and defaults to `UTC`, and Genesis validates cron field ranges plus IANA timezones before saving the schedule. To remove a schedule, pass `trigger=null` and omit other schedule keys. For `GET_VERSION`, pass `{flow_id, version_number, include_definition?}`; `include_definition` is a boolean that defaults to `true`. Set it to `false` to return Flow/version identity, ownership, name, schedule, and `definition_sha256` without the saved source definition; the response sets `definition_included` to `false`. For `GET_RUN`, pass `{run_id, wait_for_completion?, timeout_seconds?, poll_interval_seconds?}`. Active runs also return top-level `tool_result_status` and `next_poll_seconds` hints for the rare case where you must poll; a run launched from a thread reports back on its own instead. `tool_result_status` can be `interrupted` when infrastructure or a process restart stops the run without a user cancellation. For managed sources: `REGISTER_MANAGED_SOURCE` accepts `{repo_id, remote_url?, connection?, release_ref?, flows_root?, auto_promote_on_sync?, flow_create_only?}`; `flow_create_only` is a boolean that defaults to `false`, refuses same-name unrelated or changed Flows, and reconciles an identical Flow from that source without updating its definition. `SYNC_FROM_REPO` accepts `{source_id or repo_id}`; `PUSH_TO_REPO` accepts `{flow_name, title?, body?, commit_message?}`; `EXPORT_PREVIEW` accepts `{flow_id or flow_name or name}`; `EXPORT_COMMIT` accepts `{flow_name or name, proposed_yaml, proposed_bindings?, source_id? or repo_id?, artifact_path?, title?, body?, commit_message?, persist_bindings?}`. After sync, use `dependency_action` to bind unresolved logical refs. |

To review a waiting change, first preview it, then pass its fingerprints back
unchanged when promoting:

```python theme={null}
flow_action(action="GET_PENDING", params={"pending_id": "pending-id"})
flow_action(
    action="PROMOTE_PENDING",
    params={
        "pending_id": "pending-id",
        "pending_fingerprint": "fingerprint-from-preview",
        "live_fingerprint": "live-fingerprint-from-preview",
    },
)
```

`CREATE`, `UPDATE`, `RUN`, `REVERT`, `PROMOTE`, `PROMOTE_PENDING`, `FORK_TO_STANDALONE`, `DELETE`, `SCHEDULE`, and `CANCEL_RUN` refuse unrecognized keys in `params`; the response lists `unknown_params` and `accepted_params`, and nothing changes. `UPDATE`'s `steps` replaces the entire list rather than merging it: GET the flow first, then send every step it should retain and any new steps. The response includes `step_count_before` when the prior list is readable and always includes `step_count` for the replacement.

Flow runs started from a chat report terminal results back to the launching
conversation; see [A run started from a chat reports back to it](/docs/User-Guide/Flows#a-run-started-from-a-chat-reports-back-to-it)
for delivery timing and payload details.

When `RUN` starts a flow from a conversation, its response includes `notify: true`
and a `next_step` telling the agent to continue with other work; the run reports
back on the next tool result or as a new turn when the thread is idle. For a run
without a launching thread, `notify` is `false` and `next_step` directs the agent
to read the run with `GET_RUN`. External MCP and `/api/tool_call` callers also
receive `notify: false`; see [the Flow run delivery guidance](/docs/User-Guide/Flows#a-run-started-from-a-chat-reports-back-to-it).
Treat `wait_for_completion` as a last resort for
short waits when the outcome is required before continuing, not as the normal
polling path.

See [Flows](/docs/User-Guide/Flows#move-a-table-between-registered-connections) for the
`bulk_copy` step's external-target recipe, supported connection types, and transfer
limits. `CREATE` and `UPDATE` reject a `bulk_copy` definition unless it has a source
(`query` or `source_table`) and an output target that can accept a whole relation.

See [Flows](/docs/User-Guide/Flows#move-a-table-between-registered-connections)
for step timeout, concurrency, cancellation behavior, and external-write result
semantics, including the guarantee that a copy stopped before its final target
statement leaves the target unchanged.
That section also documents the `values_nulled` result field for SQLite empty
strings written as `NULL`, and the numeric-column outcomes reported by bulk copy.

Successful `CREATE`, `GET`, `GET_VERSION`, `UPDATE`, `REVERT`, and
`VALIDATE_DEFINITION` responses include `definition_sha256`: a canonical
SHA-256 fingerprint of the portable execution fields (`description`,
`parameters` / `parameters_schema`, `steps`, `on_failure`, `tags`, and
`schedule` when present). The hash excludes the instance-local Flow name so
you can compare a reviewed candidate to the definition you are about to apply,
revert, or promote without name drift.

`SYNC_FROM_REPO` runs in the active bot context, so the same managed repository
can hydrate separate Flow records for different bots. Managed source `include`
/ `exclude` selectors narrow which flow artifacts `SYNC_FROM_REPO` enables.
Flows that no longer match are retired on sync:
disabled, cron schedule removed from the scheduler, and managed dependency rows
cleared. Genesis retires only flows this source created (`managed_sync:<source_id>`);
a local flow with the same name stays enabled and scheduled.

For `flow_action` `SCHEDULE`, cron strings must contain exactly 5 fields in
`minute hour day month day_of_week` order. If you pass a structured Flow cron
trigger instead of a cron string, use `minute`, `hour`, `day_of_month`,
`month`, and `day_of_week`; Genesis normalizes `day_of_month` to the
scheduler's `day` field when it syncs the saved Flow schedule.

For sandbox-backed Python steps, `params.steps[*].sandbox_backend_options` can also include saved `target_env` and `security_profile` names created through `sandbox_env`. At execution time Genesis merges those settings in this order:

1. `target_env` defaults
2. `security_profile` defaults
3. explicit `sandbox_backend_options` values on the step

That means step-level values still win for per-run overrides such as `credential_name`, `namespace`, or other backend-specific options. A typical step fragment looks like `{"execution_target":"sandbox","sandbox_backend_options":{"target_env":"railway-analytics","security_profile":"analytics-reader","credential_name":"railway-prod"}}`.

When you declare flow input parameters, use either `parameters_schema` or the
equivalent `parameters` alias. In either form, each entry can be a simple type
alias or a full object such as `{"n":{"type":"int","required":true},"flag":{"type":"bool","default":"true"}}`.

<Note>
  For one-shot model work inside a Flow Python step, use
  `genesis_flow.llm.ask(...)`. `model_tier` and `provider` are optional;
  omitting them inherits the flow authoring thread defaults when available and
  otherwise falls back to the flow bot's default tier/provider resolution.
  Legacy `model="fast"`, `model="main"`, and `model="frontier"` still map to
  tiers, and the helper returns `result.output` plus `result.usage` with the
  resolved provider/model details. Use **forward** calls when downstream steps
  or branches must parse the model output; use **side-channel** calls for
  optional narrative or audit text that must not gate the pipeline. The built-in
  **app-flow-llm-usage** AgentSkill documents the same pattern for Genesis Apps.
</Note>

<Note>
  Flow SQL steps cannot persist namespace-level `CATASTROPHIC` operations such
  as `DROP DATABASE`, `DROP SCHEMA`, `DROP CATALOG`, or `CREATE OR REPLACE
      DATABASE/SCHEMA/CATALOG`. Flows run unattended and cannot provide the
  interactive `user_override` these operations require, so run those statements
  as one-off `_query_database` calls instead.
</Note>

For Flow step connection-name forms and external output configuration errors,
see [Move a table between registered connections](/docs/User-Guide/Flows#move-a-table-between-registered-connections).

Example:

```text theme={null}
flow_action(
  action="SCHEDULE",
  params={"flow_id":"daily_sales","schedule":"0 9 * * *","timezone":"America/Los_Angeles"}
)

flow_action(
  action="SCHEDULE",
  params={"flow_id":"daily_sales","trigger":null}
)

flow_action(
  action="GET_RUN",
  params={
    "run_id":"run_123",
    "wait_for_completion":true,
    "timeout_seconds":60,
    "poll_interval_seconds":5
  }
)

flow_action(
  action="CREATE",
  params={
    "flow_id":"daily_sales",
    "parameters":[
      {"name":"n","type":"int","required":true},
      {"name":"flag","type":"bool","default":"true"}
    ]
  }
)
```

### `inspect_flow_failure`

Inspect the persisted execution evidence for a failed Genesis Flow run. Call this
before making any causal claim when an alert supplies a run ID, asks for
root-cause analysis, or reports that a pipeline exhausted retries.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `run_id` | string | none | Required. Durable Genesis Flow run ID from the incident alert. |

On success, returns `success: true` with `evidence` (run/job/task identities,
historical task definition, bounded preceding-step evidence, connection identity,
retry exhaustion, timestamps, error log, repository/orchestrator pointers),
`inspection_receipt` (thread-scoped receipt stamped in the current thread),
`required_citations` (exact `label=value` strings to copy into finalization),
and `existing_outcome` (any prior RCA outcome on the run, or `null`). On
failure, returns `success: false` with `error`.

For failed steps that write to external targets, the persisted `error log` uses
the masked or withheld form described in [Flows → Inspect a flow or run](/docs/User-Guide/Flows#inspect-a-flow-or-run),
including recognized quoted target column names while target values remain masked.

For ordinary Flow CRUD or successful run status use `flow_action` instead.
After correcting the Flow, use `run_flow_rca_verification` for durable
completion; use `record_flow_rca_outcome` for staged work or manual recovery.
If a downstream tool reports a missing or mismatched receipt, call this again in
the same thread.

### `run_flow_rca_verification`

Finish an inspected Flow RCA with verified correction and durable evidence in
one combined operation. This tool runs (or reuses) a linked `rca_verification`
Flow run on a newer Flow version, then atomically persists the corrected RCA
outcome and protected gold record. If protected gold already exists for the
failed run, Genesis returns the canonical outcome without re-running verification
or overwriting the protected record.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `failed_run_id` | string | none | Required. The inspected failed Flow run ID from `inspect_flow_failure`. |
| `root_cause` | string | none | Required. Concrete causal finding grounded in inspected task code/logs; name the broken assumption and observed mismatch. Must be at least 20 characters. |
| `evidence_citations` | string\[] | none | Required. Copy every exact value from `inspect_flow_failure.required_citations` into this list. |
| `remediation_summary` | string | none | Required. Exact correction applied to the current Flow and verified by this call. Must be at least 20 characters. |

Prerequisites:

* A matching `inspect_flow_failure` receipt in the current thread.
* The current Flow version must be newer than the failed run's version.
* `evidence_citations` must include every value from `required_citations`
  (run ID, task ID, connection ID, error-log SHA-256, Flow version, retry
  exhaustion, attempts, and repository or flow-store version pointer).

On success, returns `success: true` with `task_durably_complete: true`,
`failed_run_id`, `verification` (linked verification run ID, status, Flow
version, timestamps), `gold` (`gold_id` and status), `canonical_evidence_citations`,
`already_completed` (whether protected gold already existed),
`verification_reused` (whether an existing completed verification run was
reused), `thread_context_persisted`, and `next_action` (instructions to restate
the cited result in the next assistant message). On failure, returns
`success: false` with `error` and may include `run` when verification execution
failed.

Prefer this tool for normal corrected completion. Use `record_flow_rca_outcome`
only for staged work or manual recovery when a completed linked verification
already exists. Do not call `record_flow_rca_outcome` after a successful terminal
receipt from this tool.

Example:

```text theme={null}
inspect_flow_failure(run_id="run_abc123")
# ... correct the Flow to a newer version ...
run_flow_rca_verification(
  failed_run_id="run_abc123",
  root_cause="The failed SQL step referenced customer_tier but the probe showed customer_segment is the actual column name.",
  evidence_citations=[
    "run_id=run_abc123",
    "task_id=step_query",
    "connection_id=snowflake.analytics",
    "error_log_sha256=...",
    "flow_version=3",
    "retry_exhausted=true",
    "attempts=3/3",
    "flow_store_version=my_flow@3"
  ],
  remediation_summary="Updated the SQL step to select customer_segment instead of customer_tier and promoted Flow version 4."
)
```

### `record_flow_rca_outcome`

Preserve a staged Flow RCA or manually recover corrected finalization. Use this
after `inspect_flow_failure` when correction cannot yet run and you need to save
an exact staged next action, or when a completed linked verification already
exists and the combined finalizer needs manual recovery.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `run_id` | string | none | Required. Failed Genesis Flow run ID that was inspected. |
| `root_cause` | string | none | Required. Concrete causal finding grounded in inspected task code/logs. Must be at least 20 characters. |
| `evidence_citations` | string\[] | none | Required. Copy every exact value from `inspect_flow_failure.required_citations`. |
| `remediation_status` | string | none | Required. `staged` or `corrected`. |
| `remediation_summary` | string | none | Required. Exact remediation executed or staged, including how it will be verified. Must be at least 20 characters. |
| `verification_run_id` | string or null | `null` | Required when `remediation_status='corrected'`. Must reference the exact current newer completed same-Flow RCA verification linked to this failure and inspection thread. Omit for `staged`. |

On success, returns `success: true` with `outcome`, `protected_gold` (present
only for corrected outcomes backed by verification; `null` for staged),
`already_completed` (whether protected gold already existed), and
`thread_context_persisted`. Staged outcomes update the run's `rca_outcome` but do
not create protected gold. On failure, returns `success: false` with `error` and
may include `required_citations` when citation validation fails.

For raw evidence use `inspect_flow_failure`; for ordinary Flow work use
`flow_action`. Prefer `run_flow_rca_verification` for normal corrected
completion.

<a id="feed-metadata-review-tools" />

## `feed_metadata_review_tools`

Review a proposed `feed_metadata` onboarding row against its source, intermediate
silver, and BigQuery publish contracts before human approval. The review is
offline and uses only the row, mapping evidence, runtime type overrides, and DDL
supplied in the call; no configuration or connection is required.

### `review_proposed_feed_metadata`

Use this tool when authoring or reviewing a feed mapping, especially when the
migration includes source-to-target casts, audit fields, data-quality rules, or
SAP identifiers. Supply source declarations and rule evidence separately in
`mapping_rules`; the proposed row is not treated as proof of its own behavior.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `proposed_row` | object | none | Required JSON `feed_metadata` row, including `schemaDetails` and `bqSchema`. |
| `column_overrides` | object\[] | none | Required proposed `column_data_type_override` entries. |
| `mapping_rules` | object | none | Required source, reader, field, audit, legacy-behavior, and qualified-table evidence. For a CSV or TSV read, directly or through `cloudFiles.format`, in any mode other than `FAILFAST`, include `short_row_guard` evidence. |
| `silver_ddl` | string | none | Required `CREATE TABLE` DDL for the qualified intermediate Databricks silver table. |

The result contains:

* `valid` — `true` only when no blocking contract errors are found.
* `findings` — errors and unresolved-evidence warnings, each with `code`,
  `severity`, and `detail`.
* `stages` — the intermediate silver business type (`STRING`) and the typed
  BigQuery `publish_schema`.
* `ready_for_parity_claim` — always `false` until independent source behavior is
  proven; missing RCTL records or stored-procedure behavior must be supplied by a
  source owner.

The review rejects reader configurations that can silently change values:
`inferSchema` or `cloudFiles.inferColumnTypes` enabled, non-empty `schemaHints` or
`cloudFiles.schemaHints`, and `DECIMAL` or `NUMERIC` types without precision.
The SAP identifiers `REQUESTID`, `MATNR`, `WERKS`, `MEINS`, `EBELN`, `EBELP`,
`VBELN`, and `VBELP` must map to a `STRING` publish field with a `preserve` cast;
feed-rule artifacts additionally require both source and target types to be `STRING`.
A CSV or TSV reader, directly or through
`cloudFiles.format`, whose mode is not `FAILFAST` must also provide evidence in
`mapping_rules` that short rows are routed to the error table:

```json theme={null}
{
  "short_row_guard": {
    "detect": "field_count_below_schema",
    "evidence": "Reviewed evidence describing short-row routing to the error table"
  }
}
```

Use either `evidence` or `pilot_assumption` with non-blank reviewed text. The
guard is evidence checked by the review tool; it does not configure the reader or
route rows at runtime. Without `FAILFAST` or valid guard evidence, the review
reports a blocking finding because short rows may be null-padded or dropped
without being counted.

```python theme={null}
review_proposed_feed_metadata(
    proposed_row=feed_metadata_row,
    column_overrides=column_data_type_overrides,
    mapping_rules=reviewed_mapping_rules,
    silver_ddl="CREATE TABLE catalog.schema.feed (...)",
)
```

### `propose_feed_metadata_from_mapping`

Use this tool to draft a reviewable `feed_metadata` row from a separately
reviewed mapping manifest and a pinned target template. It derives the row and
column override changes, preserves provenance, reports explicit unknowns, and
runs the feed contract review. The result is a proposal only: its
`approval_status` is always `pending_human_review`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `mapping_manifest` | object | none | Required reviewed mapping manifest containing `review_ref`, source and reader provenance, rules, row updates, column overrides, and template override dispositions. |
| `target_template` | object | none | Required pinned template containing a `row` and any template `column_overrides`. |
| `pinned_template_sha256` | string | none | Required SHA-256 hash of the target template's canonical JSON. |
| `silver_ddl` | string | none | Required `CREATE TABLE` DDL for the intermediate Databricks silver table. |

The tool validates the template pin and mapping provenance before proposing
changes. Each operative template cast for a publish field needs an evidenced
`retain`, `replace`, or `remove` disposition; generic overrides for absent
columns are derived from the difference. Missing pin, provenance, or required
override evidence raises a validation error. Do not fill missing cast,
data-quality, default, or exception rules from sample rows.

The result contains:

* `row` and `column_overrides` — the proposed feed row and runtime type overrides.
* `row_diff` and `override_diff` — changes from the target template, with
  provenance and override dispositions.
* `row_provenance` and `override_provenance` — evidence references for proposed values.
* `unknowns` and `review` — unresolved behavior and the existing feed contract review.
* `approval_status`, `template_sha256`, and `mapping_review_ref` — review state and
  proposal provenance.

```python theme={null}
propose_feed_metadata_from_mapping(
    mapping_manifest=reviewed_mapping_manifest,
    target_template=pinned_target_template,
    pinned_template_sha256=template_sha256,
    silver_ddl="CREATE TABLE catalog.schema.feed (...)",
)
```

<a id="gcs-tools" />

## `gcs_tools`

Google Cloud Storage (GCS) object storage: list buckets, list objects, download
objects, and preview small text objects using a saved **Google Cloud** (`gcp`)
service-account connection. This is the GCS analogue of the S3 read path in
`aws_action`. It reuses the same `gcp` connection type that powers
[gcp\_cloudrun\_tools](#gcp-cloudrun-tools) — no separate connection type is
required. Create the connection under **Config → Connections** with
**Service Account** credentials (`project_id`, `client_email`, `private_key`).

### `gcs_action`

Use this function to list buckets, list objects in a bucket (optionally by
prefix), download one object into the bot git repo, or preview a small text
object inline. Start with `list_buckets` or `list_objects` to confirm
authentication before downloading.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `list_buckets`, `list_objects`, `download_file`, or `read_object`. |
| `credential_name` | string | none | Required for all actions. Name of a saved `gcp` service-account connection. |
| `bucket_name` | string | none | Required for `list_objects`, `download_file`, and `read_object`. GCS bucket name. |
| `prefix` | string | none | Optional for `list_objects`. Object-name prefix filter (for example `raw/2024/`). |
| `object_name` | string | none | Required for `download_file` and `read_object`. Full GCS blob path (for example `raw/2024/transactions.csv`). |
| `file_path` | string | none | Required for `download_file`. Repo-relative destination path (for example `raw/report.csv`). |
| `repo_id` | string | `uploads` | Optional for `download_file`. Bot git repo id that `download_file` writes into. |
| `max_results` | integer | `100` | Optional for `list_objects`. Maximum objects to return (capped at `1000`). |
| `encoding` | string | `utf-8` | Optional for `read_object`. Text encoding used when decoding the object. |

#### Actions

| Action | Required parameters | Notes |
| - | - | - |
| `list_buckets` | `credential_name` | Returns `buckets` (each with `name` and `creation_date`) and `count`. |
| `list_objects` | `credential_name`, `bucket_name` | Returns `objects` (each with `name`, `size`, `updated`, `storage_class`, and `content_type`), plus `bucket`, `prefix`, and `count`. |
| `download_file` | `credential_name`, `bucket_name`, `object_name`, `file_path` | Writes to `BOT_GIT/repos/<repo_id>/<file_path>` and refuses paths that escape the repo, name or resolve into `.git` metadata, or resolve outside the repository. Returns `local_file`, `repo_id`, `full_path`, `bytes_downloaded` (the number of bytes actually written to disk), and `message`. |
| `read_object` | `credential_name`, `bucket_name`, `object_name` | Returns `content`, `size`, `content_type`, and `encoding`. Refuses objects larger than 1 MiB — use `download_file` instead. |

On success, responses include `success: true` plus action-specific fields. On
failure, responses include `success: false` with an `error` string.

Example:

```text theme={null}
gcs_action(action="list_buckets", credential_name="gcp-prod")
gcs_action(
  action="list_objects",
  credential_name="gcp-prod",
  bucket_name="analytics-landing",
  prefix="raw/2024/",
  max_results=50
)
gcs_action(
  action="download_file",
  credential_name="gcp-prod",
  bucket_name="analytics-landing",
  object_name="raw/2024/report.csv",
  file_path="imports/report.csv"
)
gcs_action(
  action="read_object",
  credential_name="gcp-prod",
  bucket_name="analytics-landing",
  object_name="raw/2024/sample.jsonl"
)
```

<a id="gcp-cloudrun-tools" />

## `gcp_cloudrun_tools`

Build and deploy applications to Google Cloud Run and related GCP delivery services.

`gcp_cloudrun` accepts `tail_lines` (integer, default `100`) for the
`GET_BUILD_LOGS` action. `bot_id` and `thread_id` are implicit from the acting
agent context; `user_id` is implicit from the requesting user context.

<a id="gcp-secrets-tools" />

## `gcp_secrets_tools`

Store and retrieve secrets through GCP Secret Manager. It pairs naturally with Cloud Run deployment workflows.

`gcp_secrets` receives `bot_id` and `thread_id` implicitly from the acting agent
context and `user_id` implicitly from the requesting user context. Its
`page_size` parameter is an integer with default `50` and controls the number of
results returned for list actions.

<a id="genesis-enhancement-tools" />

## `genesis_enhancement_tools`

Create, synchronize, and package Genesis enhancement or support requests, including automatic `CREATE_REPORT` submission when configured, plus offline ZIP-based exchanges.

### `genesis_enhancement_action`

Use this function to create, inspect, update, submit, and synchronize Genesis support or enhancement reports. For support workflows, `CREATE_REPORT` can export a thread, attach the resulting bundle directly to the report, and return a `delivery` object that tells you whether Genesis actually submitted the ticket.

The requesting user's identity is supplied implicitly for report attribution;
see the [Genesis Enhancement API report fields](/docs/Genesis-API/API-Reference#report-list-endpoint).

#### Key parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `CREATE_REPORT`, `BATCH_CREATE_REPORTS`, `LIST_REPORTS`, `GET_REPORT`, `UPDATE_REPORT`, `SUBMIT_REPORT`, `SYNC_STATUS`, `ADD_FEEDBACK`, `GET_SUMMARY`, `GET_SETTINGS`, `UPDATE_SETTINGS`, `EXPORT_ZIP`, `IMPORT_STATUS_ZIP`, `START_CURSOR_AGENT`, `GET_CURSOR_AGENT_STATUS`, or `FOLLOWUP_CURSOR_AGENT`. |
| `title` | string | `null` | Required for `CREATE_REPORT`. Report title. |
| `ticket_type` | string | `enhancement` | For `CREATE_REPORT` and `LIST_REPORTS`: `support` or `enhancement`. |
| `attach_thread_id` | string or null | current thread when available | For `CREATE_REPORT`: thread ID to export and attach as a report artifact. Pass `current` explicitly to attach the active conversation, or omit it to auto-attach when the tool has thread context. |
| `include_server_log` | boolean or null | `true` | For `CREATE_REPORT` with `attach_thread_id`: include `server.log` in the export when allowed by workspace policy. The tool opts in by default; pass `false` to skip it. |
| `bug_report` | string or null | `null` | For `CREATE_REPORT`: Markdown bug report content bundled into the attached ZIP as `bug_report.md`. |
| `online_hint` | boolean | `true` | For `CREATE_REPORT`, `SUBMIT_REPORT`, and `BATCH_CREATE_REPORTS`: whether connectivity is currently available for online delivery. |
| `force_mode` | string or null | `null` | For `CREATE_REPORT`, `SUBMIT_REPORT`, and `BATCH_CREATE_REPORTS`: override submit mode with `auto`, `online`, or `offline`. |
| `auto_submit` | boolean | `true` | For `CREATE_REPORT`: when `true`, Genesis attempts to submit the new report immediately after creation and records the actual outcome in `delivery`. Set `false` to create the ticket without attempting submission. |
| `bot_id` | string or null | implicit | Optional agent ID used when exporting `attach_thread_id`. Genesis normally derives it from the acting agent context; attached-thread exports fall back to `Eve` if no bot ID is available. |
| `zip_file_path` | string or null | `null` | Export destination or import source for `EXPORT_ZIP` and `IMPORT_STATUS_ZIP`. Required for `IMPORT_STATUS_ZIP`. |
| `task_prompt` | string or null | `null` | For `START_CURSOR_AGENT`: natural-language coding task for the internal Cursor Agent. When `report_id` is provided, Genesis starts from that enhancement report instead. |
| `model` | string or null | `null` | For `START_CURSOR_AGENT`: optional model override for the selected coding backend. The model name is backend-specific; when omitted, Genesis uses the backend's configured default. |
| `idempotency_seed` | string or null | `null` | For `START_CURSOR_AGENT`: stable caller-owned seed used to deduplicate Cursor Cloud launches, such as a connection-and-ticket identifier. When omitted or blank, Genesis falls back to the per-run `run_id`. |
| `report_id` | string or null | `null` | For report-scoped actions including `START_CURSOR_AGENT` and `GET_CURSOR_AGENT_STATUS`. On `GET_CURSOR_AGENT_STATUS`, `agent_id` takes precedence when provided. When both are omitted, returns the global launcher summary. |
| `agent_id` | string or null | `null` | For `GET_CURSOR_AGENT_STATUS`: Cursor Cloud agent ID for an exact keyed lookup (takes precedence over `report_id`). For `FOLLOWUP_CURSOR_AGENT`: the Cursor Cloud agent ID to steer (required). |
| `followup_prompt` | string or null | `null` | For `FOLLOWUP_CURSOR_AGENT`: follow-up instruction to send to an existing Cursor Cloud agent. The follow-up runs in the agent's existing context (same repo, branch, and model). Accepted only when the agent is idle; if the current run is still active, the call returns `success: false` with `busy: true` and `retryable: true` — poll `GET_CURSOR_AGENT_STATUS` until the run is terminal, then retry. |
| `cloud_run_id` | string or null | `null` | For `GET_CURSOR_AGENT_STATUS` with `agent_id`: optional Cursor Cloud run ID for `/v1/agents/{agent_id}/runs/{cloud_run_id}` polling. |

If the tool has an active thread context, omitting `attach_thread_id` auto-attaches that thread. `attach_thread_id="current"` forces the same behavior explicitly.

When report attachments are created, the report payload includes an `attachments` array that the Support and Enhancements UI exposes as downloadable files.

Successful `CREATE_REPORT`, `UPDATE_REPORT`, and most `SUBMIT_REPORT` calls can also include a `bundle` object for the scrubbed support ZIP and its delivery affordances. The ZIP contains `report.md`, `report.json`, `scrub_manifest.json`, and any attached artifacts collected for the report. When bundle scrubbing is enabled, Genesis redacts supported text artifacts before packaging and leaves binary attachments unchanged. `download_url` is returned as a root-relative Genesis link on the current origin, resolving as `/api/git/...` in standalone and local deployments and `/git/...` in SPCS.

`UPDATE_REPORT` always regenerates `bundle` from the current report content after a successful update. `SUBMIT_REPORT` also attaches a fresh `bundle` when delivery did not succeed online (`queued_offline`, `send_failed`, `receiver_not_configured`, and similar outcomes) so manual follow-up links reflect the latest report. When `SUBMIT_REPORT` returns `success: true` with `mode: online`, Genesis omits a redundant local `bundle` because the receiver already received the artifacts.

| Response field | Type | Description |
| - | - | - |
| `download_url` | string | Direct ZIP download URL. |
| `download_link` | string | Markdown link string formatted as `[filename](download_url)` for chat-friendly rendering. |
| `filename` | string | ZIP filename. |
| `size_bytes` | integer | ZIP size in bytes. |
| `scrub_status` | string | Bundle scrub-manifest status: `ok`, `disabled`, or `error`. |
| `title_truncated` | boolean | Whether the report title was clipped on a word boundary for the generated email subject. |
| `eml_url` | string | Download URL for a pre-filled `.eml` draft with the scrubbed ZIP already attached. Present only when `scrub_status` is `ok`. |
| `eml_link` | string | Markdown link string for the `.eml` draft. Present only when `scrub_status` is `ok`. |
| `mailto_url` | string | Prefilled `mailto:` URL to the configured support address. Users attach the ZIP manually. Present only when `scrub_status` is `ok`. |
| `mailto_link` | string | Markdown link string for the `mailto:` fallback. Present only when `scrub_status` is `ok`. |

For generated email affordances, titles longer than 120 characters are clipped at a word boundary and marked with an ellipsis in the subject only. The report body includes the full title.

Successful `CREATE_REPORT` calls also include a `delivery` object that reports the actual submit outcome instead of implying the report was queued.

| Response field | Type | Description |
| - | - | - |
| `status` | string | One of `submitted`, `queued_offline`, `receiver_not_configured`, `send_failed`, `submit_error`, or `submit_skipped`. |
| `message` | string | Human-readable delivery outcome. Surface this when Genesis did not submit the ticket. |
| `user_action_required` | boolean | Whether the user still needs to send the bundle manually. |
| `ticket` | object or null | Present on `submitted` when the receiver returns downstream ticket details such as `ticket_id`, `ticket_key`, `ticket_url`, and `status`. |
| `error` | string or null | Failure detail for `send_failed` or `submit_error`. |
| `report` | object or null | Updated saved report payload after submission, when available. |

When `delivery.status` is `submitted`, share `delivery.ticket.ticket_url` if it is present and stop there. Otherwise quote `delivery.message`, then offer `eml_link`, `mailto_link`, and `download_url` in that order. `download_link` is the Markdown-formatted equivalent of the final fallback.

`GET_SETTINGS` returns the current enhancement settings, and `UPDATE_SETTINGS` accepts a partial `settings` object. Bundle-delivery fields in that object are:

| Setting | Type | Default | Description |
| - | - | - | - |
| `scrub_bundle_enabled` | boolean | `true` | Scrub supported text artifacts before Genesis writes support and enhancement ZIP bundles. Set `false` to preserve original text. |
| `scrub_extra_terms` | string\[] | `[]` | Additional case-insensitive whole-word terms to redact from scrubbed text artifacts. |
| `support_email_address` | string | `support@genesiscomputing.ai` | Recipient used for `bundle.eml_*` and `bundle.mailto_*` support-delivery links. |

Omit a field in `UPDATE_SETTINGS` to keep the currently stored value.

#### Cursor Agent actions

`START_CURSOR_AGENT`, `GET_CURSOR_AGENT_STATUS`, and `FOLLOWUP_CURSOR_AGENT`
use the same launcher as the **Software Factory** page. Genesis resolves
Cursor Cloud credentials from the calling user and bot context when the cloud
adapter is active.

Together these actions form a dispatch → watch → steer lifecycle:

| Action | Required inputs | Returns |
| - | - | - |
| `START_CURSOR_AGENT` | `task_prompt` or `report_id` | `cursor_agent` run metadata (`status`, `adapter`, `run_id`, `agent_id`, `cloud_run_id`, `agent_url`, `branch_name`, `pr_url`, and related fields). |
| `GET_CURSOR_AGENT_STATUS` | Optional `agent_id`, optional `cloud_run_id`, or optional `report_id` | When `agent_id` is set, polls Cursor Cloud directly and returns a compact `cursor_agent` object (`status`, `branch_name`, `pr_url`, `agent_url`, `cloud_run_id`, `last_error`). With `report_id`, returns report-scoped status. When neither is set, returns the global summary (`enabled`, `configured`, `active_run`, `latest_run`, `recent_runs`). |
| `FOLLOWUP_CURSOR_AGENT` | `agent_id`, `followup_prompt` | On success, a compact `cursor_agent` object with `agent_id`, `cloud_run_id`, and `status` for the new follow-up run. When the agent's current run is still active, returns `success: false`, `busy: true`, and `retryable: true` — poll `GET_CURSOR_AGENT_STATUS` until terminal, then retry. The selected backend must support follow-up sessions; in-flight interruption is not supported. |

The action names retain `CURSOR_AGENT` for compatibility, but dispatch through
the provider-neutral backend selected by
`genesis_enhancements.coding_agent.backend`. Cursor Cloud supports multiple
concurrent runs; Claude Code uses a per-run worktree and is bounded by
`genesis_enhancements.coding_agent.claude_code.max_concurrent_runs` (default
`1`). `FOLLOWUP_CURSOR_AGENT` is supported when the selected backend exposes
follow-up sessions; an active Claude Code run returns `busy: true` and
`retryable: true` until it reaches a terminal state.

For Linear automation, each queued attempt has its own orchestration thread and
idempotency seed. Keep that seed unchanged for the lifetime of one attempt, but
use a new seed when an issue is re-queued after a failed attempt; a previous
terminal run is not reused for the new dispatch.

The launcher is enabled by the selected backend. Cursor uses
`genesis_enhancements.cursor_agent.enabled`; Claude Code uses
`genesis_enhancements.coding_agent.backend: claude_code` and
`genesis_enhancements.coding_agent.claude_code.enabled`. Configure a **local**
Cursor runner with `CURSOR_AGENT_RUNNER_COMMAND`, a **cloud** Cursor adapter
with a shared [Cursor connection](/docs/Setup/Cursor) plus
`genesis_enhancements.cursor_agent.connection_name` and
`genesis_enhancements.cursor_agent.target_repo_url`. On the **cloud** adapter,
set `genesis_enhancements.cursor_agent.model` to pin a Cursor Cloud model slug
for new runs (empty string inherits the Cursor workspace default), or pass
`model` on a `task_prompt` start to override that setting for one run. For
Claude Code, configure the `claude_code` connection, target repository, and
GitHub connection described in [Cursor and Claude Code coding backends](/docs/Setup/Cursor#claude-code-backend).
See [Support and Enhancements — Software Factory](/docs/Setup/Support-And-Enhancements#software-factory).

Example:

```text theme={null}
genesis_enhancement_action(
  action="START_CURSOR_AGENT",
  task_prompt="Add unit tests for the dormant-review scheduler settings API."
)
```

Example:

```text theme={null}
genesis_enhancement_action(
  action="GET_CURSOR_AGENT_STATUS"
)
```

Example:

```text theme={null}
genesis_enhancement_action(
  action="START_CURSOR_AGENT",
  task_prompt="Implement GEN-2268 Linear automation polling.",
  idempotency_seed="linear-shared-GEN-2268-attempt-a1b2c3d4e5f6"
)
```

Example:

```text theme={null}
genesis_enhancement_action(
  action="START_CURSOR_AGENT",
  task_prompt="Add regression tests for the dormant-review scheduler API.",
  model="gpt-5.5-high"
)
```

Example:

```text theme={null}
genesis_enhancement_action(
  action="GET_CURSOR_AGENT_STATUS",
  agent_id="bc-01234567-89ab-cdef-0123-456789abcdef",
  cloud_run_id="run_abc123"
)
```

Example:

```text theme={null}
genesis_enhancement_action(
  action="FOLLOWUP_CURSOR_AGENT",
  agent_id="bc-01234567-89ab-cdef-0123-456789abcdef",
  followup_prompt="Fix the failing CI checks on the open pull request."
)
```

### `discard_enhancement_report`

Use this tool when a support or enhancement ticket was filed in error and has not
been sent to Genesis online. It accepts reports with status `draft`, `queued`, or
`send_failed`. A report handed over in an offline export may already be with
Genesis; if it later returns with Genesis's status, it cannot be discarded here.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `report_id` | string | none | Required. Report ID, such as one returned by `LIST_REPORTS` or `GET_REPORT`. |
| `reason` | string | none | Required. Why the report was filed in error; the reason is retained on the report. |

Discarded reports remain as records with status `discarded` and the discarder's
identity, time, and reason. They stop appearing in report lists, summaries, and
unsent exports; `LIST_REPORTS` with `status="discarded"` can still retrieve them.
Discarding the same report again changes nothing. Reports already sent to Genesis
are refused; use `genesis_enhancement_action` with `ADD_FEEDBACK` to explain why a
sent report is no longer needed, or `UPDATE_REPORT` to correct its content.

The caller needs either `manage_genesis_enhancements` or `access_config_panel`.
A successful call returns `success`, `report_id`, `title`, `status`, and the
`discard` details. A refusal returns `success: false` with an error.
Each call reads the report store once; the first successful discard also performs
one atomic rewrite. Repeated discards and refusals do not rewrite the store.

Example:

```text theme={null}
discard_enhancement_report(
  report_id="enh_123456",
  reason="This was filed from test data and is not a real issue."
)
```

## Thread goal tools

Two tools, carried by the always-available
[`context_tools`](#context_tools) group: `get_thread_goal` and
`declare_goal_turn_status`. Use them on a thread pursuing a goal to report where the
goal stands and to close it.

Goal mode has **no checkers**. Every item on a goal's finish line is attested by the
agent pursuing it: an item reads `met` because the agent declared it met, and a goal
reaches `met` when every item does. Nothing else closes one. A blueprint phase
separately enforces its own `exit_criteria` at its exit gate, so declaring an item met
does not get a phase past a deliverable it is missing.

A thread that is pursuing a goal carries an `ACTIVE GOAL ON THIS THREAD` block in the
agent's context, re-rendered every turn and beside every tool result. **No block means
no goal**, so neither tool is the way to find out whether one exists; a thread with no
goal is told nothing at all about goals, and calls on such a thread are refused.

### `get_thread_goal`

Reads the goal and how far along it is. Takes only the implicit `bot_id` and
`thread_id`, and returns:

| Field | Description |
| - | - |
| `has_goal` | Whether this thread is pursuing a goal at all. |
| `statement` | What the goal is, in the person's own terms. |
| `finish_line_scope` | What the items cover when that is narrower than the statement — one blueprint phase, say. |
| `status` | `proposed`, `working`, `paused` or `ended`. `paused` means nothing is nudging the thread on: the agent is waiting on someone, a person paused it, or the last turn was the person's own. |
| `status_reason` | Why the goal reached its current lifecycle status. |
| `verdict` | `pursuing`, `met`, `failed` or `blocked`; `blocked` ends the goal but can be revived by a person's next turn or an agent declaration that marks nothing blocked. `met` and `failed` are final. |
| `revival` | The previous blocked ending when this goal was revived: who revived it, when, the original `blocked_on` and reason, and the item IDs reset from `blocked` to `unmet`. Null if the goal was never blocked. |
| `progress_summary` | The agent's own latest status against the goal, in its own words. |
| `questions_for_person` | Questions the agent has queued for a person while continuing the goal; an empty list means there is nothing queued. |
| `started_at_epoch` | When work on the goal started, as epoch seconds. |
| `criteria` | Finish-line items with `id`, `text` and `status` (`met`, `unmet`, `failed` or `blocked`). Every one of them is the agent's to close. If the `ACTIVE GOAL` block is in its one-line form, it shows a count instead of item IDs; get the IDs from the message that set the goal or from this field. |
| `nudges` | `used`, `limit` and `left` for nudges since the agent last reported progress. |
| `nudges_sent` | `used`, `limit` and `left` for every nudge sent to this goal; progress does not reset this lifetime ceiling. |
| `nudge_budget_spent` | Whether nudging has stopped because either nudge ceiling was reached. The goal stays open for the person; it is not ended. |
| `declaration_recorded` | Whether this turn's status has been declared. |

### `declare_goal_turn_status`

Declare where the turn left the goal, before finishing any turn on a goal thread —
including a turn where nothing worked out. A turn that declares nothing counts as a turn
that made no progress. After declaring, tell the person where things stand rather than
ending the turn on the declaration.

A turn is one reply to the person, not one tool call. You can declare more than once in a
turn; the last declaration stands. If one reply crosses multiple blueprint phases,
declare for each phase before leaving it. Item IDs from a phase are refused after the
mission has left that phase, so do not wait until the end of the reply to declare them.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `stance` | string | none | Required. `progressing`, `finished`, `awaiting_person`, `awaiting_run`, `awaiting_agent` or `cannot_proceed`. Only `progressing` is carried on by a nudge. |
| `progress_summary` | string | none | Required. One or two sentences on what was done and where the goal stands, written as a progress report a person reads on a dashboard. Repeating the previous turn's summary word for word counts as reporting nothing new. |
| `criterion_status` | object or null | `null` | Map of item IDs to `met`, `unmet`, `failed` or `blocked`. Passing an item as `met` is the only thing that closes it. Omit an item to leave its status unchanged. |
| `blocked_on` | object or null | `null` | Human actions needed for items marked `blocked`. Required for each one. |
| `questions_for_person` | array of strings or null | `null` | Replace the queued questions without pausing or ending the goal. Pass `[]` to clear the queue; omit the argument to keep the existing queue. |
| `bot_id` | string or null | implicit | Acting agent, supplied from context. |
| `thread_id` | string or null | implicit | Current thread, supplied from context. |

Questions in `questions_for_person` are queued for the person while the agent carries
on. They do not pause or end the goal. `awaiting_person` pauses it until the person
replies, and resumes it on that reply. Mark an item `blocked` only when a reply on this
thread cannot move it: leave the item `unmet` and use `awaiting_person` when the person
can move it by replying or acting here. A `blocked` item ends the goal, though a
person's next turn or a later declaration with no blocked items can revive it.
`get_thread_goal` reports the previous block in `revival` after that happens.

Each stance says what the goal is waiting on, and they are not interchangeable:
`awaiting_run` is an asynchronous job the agent started, while `awaiting_agent` is
another agent owing it an answer. `finished` says the agent has nothing further to do —
with every item met that closes the goal, and with items still open it leaves the goal
for the person rather than being nudged again.

A person's reply does not pause a goal already marked `awaiting_person`; it resumes it.
For a goal that ended `blocked`, the person's next turn revives it as well. If that
blocked ending remains in effect, do not declare the same item blocked again: that
declaration is refused. Instead, report the currently true stance and statuses without
marking an item blocked, or tell the person what still needs to happen outside this
thread.

When the write is refused after the goal has been read, the error explains what was
rejected and appends a reminder that nothing was recorded and the turn currently counts
as no progress. An unknown item error also lists the goal's valid item IDs. Fix the
named issue and call again in the same turn before finishing.

```text theme={null}
declare_goal_turn_status(
    stance="finished",
    progress_summary="Validation run completed; all 7 datasets reconciled.",
    criterion_status={"validation": "met"},
)
```

A successful response includes `success`, `declared`, `explanation`, and the projected
outcome. The `declared` field echoes the accepted `stance` and `criterion_status`; the
`explanation` notes that the declaration is parked until turn end. The declaration
is recorded against the current turn and applied to the goal when the turn ends; until
then, a goal block rendered during that turn still shows the state before the
declaration. Declare finished items as you complete them: declarations from separate
turns accumulate on the goal. If you call more than once in the same turn, the later
call replaces the earlier one, so repeat every ID you still want applied. Each
declaration is parked against the goal bound when it is made — in a blueprint, the
active phase. `finish_line_after_this` maps every finish-line item ID to its status
after the declaration is reconciled. `goal_after_this` gives the goal's projected
`status`, `verdict` and resulting `questions_for_person` queue. For a goal covering one
blueprint phase the shape differs: there is **no** `status` key, because a phase-scoped
`"status": "ended"` was read as the mission ending while the phase was still open. That
shape carries `scope` and `holds_if`, plus `phase_still_open` (always `true`),
`you_still_owe` (the call that leaves the phase), `phase_finish_line` (where that
phase's finish line lands), `goal_record_status` (the lifecycle word `status` would have
held), `exits_phase` and `phase_ends_when`: `exits_phase` is always `false`, because
declaring that the finish line is met ends the goal, not the phase. The phase remains
active until you call `PROCEED_TO_NEXT_PHASE` or `EXIT_PHASE`; on the blueprint's last
phase, that call also completes the run. The phase still enforces its own exit criteria
at the exit gate. Entering another phase binds a new goal and discards a declaration
parked against the previous one. The projected status and verdict include whether the
goal is paused; use `get_thread_goal` when you need the committed record mid-turn.

If the turn outcome cannot be judged, the declaration is still recorded, but the
response returns `projection_unavailable` instead of the projected fields. Call
`get_thread_goal` to read the goal's current state.

Declare for a blueprint phase before leaving it; its item IDs are no longer valid after
the transition. Only the declaration for the goal still bound at the end of the reply
is applied, so a reply that crosses phases reports the last phase. Do not call
`declare_goal_turn_status` in the same parallel batch as `PROCEED_TO_NEXT_PHASE` or
`ENTER_PHASE`: whichever call lands first determines which phase the declaration
applies to, and a batched `finished` stance can close the goal before the phase-exit
gate runs.

### The nudge budget

A goal-mode thread is carried on by a **nudge**: when a turn ends with the goal
unfinished and nothing being waited on, Genesis sends the thread one message asking for
the next step. Only a `progressing` stance is nudged; other stances indicate that
carrying on is not what is missing. The per-progress ceiling defaults to three nudges
without progress (`goal_mode.max_nudges`), and resets when the agent reports progress.
A separate lifetime backstop defaults to 50 total nudges for the phase
(`goal_mode.max_total_nudges`) and is never reset by progress. Reaching either ceiling
stops nudging and leaves the goal open for the person — it does not end the goal or
discard the work. The limits apply to newly created goals; a running goal keeps the
limits it started with. See [Goal mode limits](/docs/Setup/Advanced-Settings#goal-mode-limits)
for configuration details.

## `autodev_lane_tools`

The **autodev\_lane\_tools** group dispatches Genesis development tickets to a
background coding run that ends in a branch, pull request, and verification
verdict. It is separate from the in-thread coding tools, which do not publish a
pull request. The `start`, `status`, and `followup` actions use the same run
metadata described above; the review actions below manage the server-owned PR
review cycle for enrolled Factory runs.

For a Factory turn, Genesis injects the shipped Factory orchestration procedure
before dispatch and supplies repository-backed coding workers with the checkout's
root rules and full repository skill catalog. The worker starts with
`factory-repo:factory-execute`; this runtime context is supplied by Genesis and
does not add a separate tool, permission, or configuration setting.

### Review actions

| Action | Required inputs | Purpose |
| - | - | - |
| `review` | `agent_id`, `cloud_run_id` | Read the current complete review snapshot, including paginated review threads and reviews. Pass `review_cursor` to continue a page. |
| `redrive` | `agent_id`, `cloud_run_id`, `review_snapshot_id`, `expected_head_sha`, accepted `findings`, `task_prompt` | Start a correction run on the same pull request for accepted findings. |
| `review_reply` | `agent_id`, `cloud_run_id`, `review_snapshot_id`, `expected_head_sha`, one `findings` item, `reply_body` | Post a substantive response for one addressed review source; fixed findings require a newly verified published correction. |
| `review_handoff` | `agent_id`, `cloud_run_id`, `review_snapshot_id`, `expected_head_sha`, `handoff_reason` | Stop automated correction and explain the specific reason and required human action. |
| `recover` | `agent_id`, `cloud_run_id`, `recovery_snapshot_id`, `recovery_kind` | Resolve a runtime blocker, accept a valid answer posted to Linear, ask a concrete human question, or record a technical stop. |

`review_source` identifies a GitHub node with `{ "kind": "thread" | "review", "id": "..." }`.
Each `findings` item includes `source`, `disposition` (`accepted`, `fixed`, or
`declined`), and code-bound `evidence`. Read a fresh snapshot when an operation
reports a stale snapshot; do not repost or start another run after an unknown
dispatch or reply result.

For enrolled Factory runs, the `factory_result` response contract and terminal
state semantics are documented in [Coding Agent run metadata fields](/docs/Genesis-API/API-Reference#coding-agent-run-metadata-fields).
The review loop is enabled by default with
`genesis_enhancements.coding_agent.review.enabled`; `max_rounds: 0` means
unlimited correction rounds, and `active_cycle_timeout_seconds` applies only
while active correction is underway. Cursor runs are not enrolled in this loop.

### Runtime recovery

When an enrolled coding run stops at a trusted runtime boundary, its status
contains `factory_result.recovery` with the blocker or pending human-answer
candidate. Call `recover` with the exact `recovery_snapshot_id` from the latest
status. Use `recovery_kind="retry"` only for a confirmed transient fault;
use `context` or `environment` only after applying the corresponding supported
change. Use `ask` with `handoff_reason` and a complete `recovery_handoff` when
the next step needs a specific human decision or access, or use `stop` with a
concrete technical reason when no useful remedy remains.

For `ask`, Genesis posts the question to the assigned Linear issue. The Linear
automation poller checks for a matching reply every
`ticket_automation.linear.poll_interval_seconds` seconds (default `60`), then
wakes the same orchestration thread. A sufficient answer starts a fresh coding
run on the same task, thread, and branch; it does not resume the prior SDK
session and does not require a manual restart. When a reply is pending, pass
its exact `recovery.candidate.id` as `recovery_answer_id` and use the current
recovery snapshot.

`recovery_handoff` must provide non-empty `reason`, `evidence`, `checked`,
`why_human`, and `resume_condition` values. The server owns Linear comments,
state transitions, recovery deadlines, and duplicate prevention.

Example:

```text theme={null}
autodev_run_action(
  action="recover",
  agent_id="agent_123",
  cloud_run_id="run_456",
  recovery_snapshot_id="run_456:sdk:permission",
  recovery_kind="ask",
  handoff_reason="Approve access to the configured repository connection.",
  recovery_handoff={
    "reason": "The coding runner was denied repository access.",
    "evidence": "The run blocker reports a permission failure from the runtime boundary.",
    "checked": "The stored connection and repository target were inspected.",
    "why_human": "A workspace administrator must grant the missing access.",
    "resume_condition": "Resume after the repository connection is authorized."
  }
)
```

Example:

```text theme={null}
autodev_run_action(
  action="review",
  agent_id="agent_123",
  cloud_run_id="run_456"
)
```

Example:

```text theme={null}
genesis_enhancement_action(
  action="CREATE_REPORT",
  title="Thread never returns from app review",
  ticket_type="support",
  attach_thread_id="current",
  include_server_log=true,
  bug_report="## Steps to reproduce\n1. Open the app review thread\n2. Wait for the tool call to hang\n"
)
```

By default, the example above attempts immediate delivery and returns `delivery` so the caller can tell the user whether the report was submitted or still needs manual follow-up.

```text theme={null}
genesis_enhancement_action(
  action="UPDATE_SETTINGS",
  settings={
    "scrub_bundle_enabled": true,
    "scrub_extra_terms": ["WidgetCo", "InternalProjectName"]
  }
)
```

<a id="google-calendar-tools" />

## `google_calendar_tools`

Create, update, list, and delete Google Calendar events for scheduling automation.

<a id="handoff" />

## `handoff`

Spawn worker threads, delegate work to another bot, and retrieve or cancel results. See [Process Manager Tools](/docs/Genbot-Toolkit/Process-Manager-Tools) for the full lifecycle.

<a id="jams-tools" />

## `jams_tools`

Interact with JAMS job scheduling systems from Genesis. This group uses the
effective default `jams` connection for the current user (My default, then Role
default) from [Connections](/docs/Setup/Connections) unless you pass a
specific `connection`, and it accepts either numeric IDs or qualified names such
as `\\Finance\\DailyClose`.

### `jams_tool`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `RTFM`, `LIST_JOBS`, `GET_JOB`, `GET_JOB_PARAMETERS`, `SUBMIT_JOB`, `GET_HISTORY`, `GET_LATEST_ENTRY`, `LIST_ENTRIES`, `GET_ENTRY`, or `LIST_FOLDERS`. |
| `connection` | string | `null` | Connection name such as `jams.production`. If omitted, Genesis uses the effective default `jams` connection for the current user. |
| `job_id` | string | `null` | Numeric JAMS job ID or qualified job name such as `\\Folder\\JobName`. Required for `GET_JOB`, `GET_JOB_PARAMETERS`, `SUBMIT_JOB`, `GET_HISTORY`, and `GET_LATEST_ENTRY`. |
| `folder` | string | `null` | Numeric folder ID or qualified folder name for `LIST_JOBS`. If omitted, Genesis resolves the root folder dynamically. |
| `parameters` | string | `null` | JSON object string for `SUBMIT_JOB`, for example `{"BusinessDate": "2026-04-02"}`. Unknown parameter names are ignored after Genesis loads JAMS `SubmitInfo`. |
| `entry_id` | integer | `null` | JAMS entry ID for `GET_ENTRY`. |
| `status` | string | `null` | Status filter for `LIST_ENTRIES`. Genesis matches the value against JAMS entry fields such as `currentState`, `finalStatus`, or `jobStatus`. |
| `limit` | integer | `null` | Maximum number of results to return. If omitted, Genesis uses the action's built-in default. |

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at runtime, so you normally only provide the business parameters above.
</Tip>

<Note>
  When multiple role defaults for `jams` conflict, Genesis returns an error directing you to set a user default or pass `connection` explicitly. See [Default connection layers](/docs/Setup/Connections#default-connection-layers).
</Note>

<Note>
  JAMS connections support **Username & Password** (JAMS API login) and **HTTP Basic (IIS/Windows)** when IIS gates the REST API. If authentication fails and Genesis detects an IIS/Windows challenge, the error suggests switching auth type in **Config -> Connections**. See [JAMS connections](/docs/Setup/Connections#jams-connections).
</Note>

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `RTFM` | Return the built-in tool manual. | none |
| `LIST_JOBS` | List jobs, optionally filtered by folder. | none |
| `GET_JOB` | Return detailed metadata for a single job. | `job_id` |
| `GET_JOB_PARAMETERS` | Return normalized parameter definitions for a job before submission. | `job_id` |
| `SUBMIT_JOB` | Submit a job for execution. | `job_id` |
| `GET_HISTORY` | Return execution history for a job. | `job_id` |
| `GET_LATEST_ENTRY` | Return the most recent entry for a job. | `job_id` |
| `LIST_ENTRIES` | List current schedule entries, with optional status filter. | none |
| `GET_ENTRY` | Return detailed metadata for a specific entry. | `entry_id` |
| `LIST_FOLDERS` | List available JAMS folders. | none |

### Submission workflow

* Use numeric IDs or qualified names such as `\\Folder\\JobName`. Avoid bare job names because they can be ambiguous across folders.
* Call `GET_JOB_PARAMETERS` before `SUBMIT_JOB` to discover valid parameter names and required fields. Genesis treats a JAMS parameter as required when the API marks either `required` or `mustFill`.
* `SUBMIT_JOB` follows the JAMS v7 swagger `SubmitInfo` flow: Genesis first fetches the job's `SubmitInfo`, applies matching `parameters`, then posts the full `SubmitInfo` object back to JAMS.
* When `SUBMIT_JOB` returns a `jamsEntry`, use `GET_ENTRY` with that ID for the most reliable status check. `GET_LATEST_ENTRY` is still useful when you need to look up the newest entry by job.

Example:

```python theme={null}
# Browse jobs in a qualified folder
jams_tool(action="LIST_JOBS", folder="\\\\Finance", limit=25)
```

```python theme={null}
# Inspect parameters, then submit a job
jams_tool(action="GET_JOB_PARAMETERS", job_id="\\\\Finance\\\\DailyClose")

jams_tool(
    action="SUBMIT_JOB",
    job_id="\\\\Finance\\\\DailyClose",
    parameters='{"BusinessDate": "2026-04-02"}'
)
```

<a id="jenkins-tools" />

## `jenkins_tools`

See [Jenkins](/docs/Setup/Jenkins) for the customer-facing setup and CI/CD workflow path. When `connection` is omitted, Jenkins tools resolve the effective default `jenkins` connection for the current user (My default, then Role default).

### `jenkins_config`

Manage the Jenkins configuration used by Jenkins tools. `SET` saves the install-wide `jenkins.shared` connection; it does not save the token to a local plaintext file or environment variable. A complete set of values replaces the shared configuration. If values are omitted, `SET` fills them from the existing shared connection. Changing the URL requires a new `api_token`; the stored token is not reused for a different server. `GET` returns the current resolved configuration with the token masked, and `TEST` checks connectivity. When testing a different URL, provide its `api_token` explicitly.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. `SET`, `GET`, or `TEST`. |
| `base_url` | string | `null` | Jenkins server URL. Used by `SET` and as an optional override for `TEST`. |
| `username` | string | `null` | Jenkins username. Used by `SET` and as an optional override for `TEST`. |
| `api_token` | string | `null` | Jenkins API token. Used by `SET` and as an optional override for `TEST`; required when setting or testing a new/different URL. |

Example:

```text theme={null}
jenkins_config(action="SET", base_url="https://jenkins.example.com", username="ci-user", api_token="your-api-token")
jenkins_config(action="GET")
jenkins_config(action="TEST")
```

<a id="matillion-tools" />

## `matillion_tools`

Operate Matillion Data Productivity Cloud projects, pipelines, and executions from
Genesis. When `connection` is omitted, Matillion tools resolve the effective default
`matillion` connection for the current user (My default, then Role default). If no
default is set and exactly one Matillion connection is accessible, that connection is
used automatically. When multiple connections exist without a default, pass
`connection` explicitly or call `LIST_CONNECTIONS` to discover available options. For
setup and workflow details, see [Matillion Connector](/docs/User-Guide/Matillion-Connector).

Use `airbyte_connector` for Airbyte data syncs instead of `matillion_connector`.
For `UPLOAD_ARTIFACT`, each publish **replaces the environment's entire published
bundle** — include every pipeline that must stay runnable in one call. Prefer
`yaml_repo_id` + `yaml_file_paths` (paths and/or globs) to publish multiple files
atomically; use `yaml_content` + `artifact_path` or `yaml_repo_id` + `yaml_file_path`

* `artifact_path` for a single file. Use [`git_action`](/docs/Genbot-Toolkit/Git-Action-Tools)
  when you only need to read, commit, or branch pipeline YAML without uploading to
  Matillion.

### `matillion_connector`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. See [Available actions](#matillion-available-actions) below. |
| `connection` | string | `null` | Optional connection name such as `matillion.production`. If omitted, Genesis uses the effective default `matillion` connection for the current user, or the sole accessible connection when only one exists. |
| `project_id` | string | `null` | Matillion project ID. Required for `LIST_PIPELINES`, `UPLOAD_ARTIFACT`, `RUN_PIPELINE`, `GET_JOB_STATUS`, `WAIT_FOR_JOB`, and `LIST_ENVIRONMENTS`; optional for `LIST_EXECUTIONS`. |
| `project_name` | string | `null` | Name for a new project (`CREATE_PROJECT`). |
| `client_id` | string | `null` | OAuth2 client ID (`SET_CREDENTIALS`). |
| `client_secret` | string | `null` | OAuth2 client secret (`SET_CREDENTIALS`). |
| `base_url` | string | `null` | Matillion base URL, for example `https://app.matillion.com` (`SET_CREDENTIALS`). |
| `artifact_path` | string | `null` | Bundle path for a single-file publish, for example `silver/build.tran.yaml` (`UPLOAD_ARTIFACT`). Required for single-file modes; omit when using `yaml_file_paths`. |
| `yaml_content` | string | `null` | Pipeline YAML content for a single-file direct publish (`UPLOAD_ARTIFACT`). Requires `artifact_path`. |
| `yaml_repo_id` | string | `null` | Genesis git repo ID to read YAML from (`UPLOAD_ARTIFACT`). Required with `yaml_file_paths` or `yaml_file_path`. |
| `yaml_file_path` | string | `null` | Path to one YAML file within `yaml_repo_id` for a single-file git publish (`UPLOAD_ARTIFACT`). Requires `yaml_repo_id` and `artifact_path`. |
| `yaml_file_paths` | string\[] | `null` | List of repo paths and/or glob patterns to publish as **one atomic bundle** (`UPLOAD_ARTIFACT`). Requires `yaml_repo_id`. Each file publishes at its repo path. Example: `['silver/*.yaml', 'silver_v2/*.yaml']`. |
| `version_name` | string | `null` | Version name for the artifact (`UPLOAD_ARTIFACT`; auto-generated when omitted). |
| `branch_name` | string | `null` | Branch name for the artifact (`UPLOAD_ARTIFACT`). |
| `environment_name` | string | `default` | Environment name (`UPLOAD_ARTIFACT`, `RUN_PIPELINE`, `LIST_PIPELINES`). |
| `pipeline_path` | string | `null` | Pipeline path, for example `baseball/batting_summary.tran.yaml` (`RUN_PIPELINE`). |
| `branch_name_run` | string | `null` | Branch to select among **published** bundles for execution (`RUN_PIPELINE`). Executions resolve from the published-artifact bundle, not the project's git link. Leave unset to use the default published bundle. |
| `runnable_only` | boolean | `false` | For `LIST_PIPELINES`: when `true`, return only the currently published (runnable) bundle and omit upload history. |
| `section` | string | `null` | For `RTFM` / `HELP`: return one manual section instead of the full manual. One of `introduction`, `quickstart`, `run_history`, `transformation`, `orchestration`, `workflows`, `patterns`, `troubleshooting`, `api_reference`, `best_practices`, `examples`. |
| `agent_id` | string | `null` | Optional agent ID for pipeline execution (`RUN_PIPELINE`). |
| `execution_id` | string | `null` | Pipeline execution ID (`GET_JOB_STATUS`, `WAIT_FOR_JOB`). |
| `status_filter` | string | `null` | Only return executions with this status, for example `FAILED` or `SUCCESS` (`LIST_EXECUTIONS`). |
| `limit` | integer | `25` | Maximum number of executions to return (`LIST_EXECUTIONS`). |
| `timeout_seconds` | integer | `300` | Timeout in seconds (`WAIT_FOR_JOB`). |
| `poll_interval` | integer | `5` | Poll interval in seconds (`WAIT_FOR_JOB`). |

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at runtime, so you normally only provide the business parameters above. When `UPLOAD_ARTIFACT` reads YAML from `yaml_repo_id`, Genesis forwards `user_id` and `bot_id` to enforce repository access policies on shared git repos — the same rules as [`git_action`](/docs/Genbot-Toolkit/Git-Action-Tools) `read_file`.
</Tip>

<a id="matillion-available-actions" />

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `RTFM` / `HELP` | Return the Matillion connector manual with YAML examples and troubleshooting. Pass `section` to fetch one chunk (for example `troubleshooting`) instead of the full manual. | none (`section` optional) |
| `SET_CREDENTIALS` | Save OAuth2 credentials. | `client_id`, `client_secret`, `base_url` |
| `TEST_CONNECTION` | Validate credentials and authenticate. | none (uses saved or passed credentials) |
| `LIST_CONNECTIONS` | List configured Matillion connections you can use (`connection_id`, `base_url`, `is_default`). Call first when unsure which connection to pass or after a connection-not-found error. | none |
| `LIST_PROJECTS` | List Matillion projects. | none |
| `CREATE_PROJECT` | Create a new project. | `project_name` |
| `UPLOAD_ARTIFACT` | Publish pipeline YAML to an environment. Each call **replaces the whole published bundle** — pipelines not included become unrunnable via the API. Bundle (recommended): `yaml_repo_id` + `yaml_file_paths`. Single file from git: `yaml_repo_id` + `yaml_file_path` + `artifact_path`. Single file direct: `yaml_content` + `artifact_path`. Git reads use injected `user_id` and `bot_id` for repository access checks. On success, check `evicted_pipelines` for pipelines dropped from the bundle. Upload failures return `status_code`, `error`, and `details` (transient 5xx are retried automatically). | `project_id`, plus one of: `yaml_repo_id` + `yaml_file_paths`, `yaml_repo_id` + `yaml_file_path` + `artifact_path`, or `yaml_content` + `artifact_path` |
| `RUN_PIPELINE` | Execute a pipeline from the **currently published** bundle (not the git link). A 404 usually means the pipeline is not published — confirm with `LIST_PIPELINES` (`runnable_only=true` or `source='published'`). | `project_id`, `pipeline_path` |
| `GET_JOB_STATUS` | Check one execution's status. | `project_id`, `execution_id` |
| `WAIT_FOR_JOB` | Poll until an execution completes or times out. | `project_id`, `execution_id` |
| `LIST_EXECUTIONS` | Run history — recent pipeline executions with per-status counts. No `execution_id` needed. | none (`project_id`, `status_filter`, and `limit` optional) |
| `LIST_PIPELINES` | Published (runnable) pipelines and artifact upload history in a project. Set `runnable_only=true` for only the published bundle. Draft pipelines are git / Designer only. | `project_id` |
| `LIST_ENVIRONMENTS` | List environments in a project. | `project_id` |

Every action returns a dict with `success`. On success, payload keys depend on the
action — for example `connections`, `count`, and `message` for `LIST_CONNECTIONS`;
`executions`, `count`, `status_counts`, and `failed_count` for `LIST_EXECUTIONS`;
`published_pipelines`, `artifact_history`, `published_count`, `artifact_count`, `pipelines`, `count`, and `note` for `LIST_PIPELINES`; `published_files`, `evicted_pipelines`, and `warning` for `UPLOAD_ARTIFACT`; `projects` for `LIST_PROJECTS`;
`status` for `GET_JOB_STATUS`. On failure the response carries `error` (sometimes with
`troubleshooting`). Recover with `TEST_CONNECTION`, `RTFM`, `LIST_CONNECTIONS`, or by
naming the Matillion connection explicitly.

`LIST_CONNECTIONS` response details:

| Response field | Type | Description |
| - | - | - |
| `connections` | object\[] | Non-secret connection summaries. Each entry has `connection_id` (for example `matillion.production`), `base_url`, and `is_default`. |
| `count` | integer | Number of connections returned. |
| `message` | string | Human-readable summary, for example `Found 2 Matillion connection(s).` or guidance when none are configured. |

`LIST_EXECUTIONS` response details:

| Response field | Type | Description |
| - | - | - |
| `executions` | object\[] | Execution rows, most recent first. Rows include `pipelineName`, `status`, `startedAt`, `finishedAt`, `trigger`, `user`, `projectId`, and `environmentName`. |
| `count` | integer | Number of executions returned. |
| `status_counts` | object | Map of uppercase status strings to counts within the returned window. |
| `failed_count` | integer | Count of `FAILED`, `ERROR`, and `CANCELLED` executions in the window. `0` means no errors found. |

`LIST_PIPELINES` response details:

| Response field | Type | Description |
| - | - | - |
| `published_pipelines` | object\[] | Pipelines in the currently published (runnable) bundle. Each row has `source` set to `published`. |
| `artifact_history` | object\[] | Prior artifact uploads. History entries are not necessarily runnable — each publish replaces the bundle. |
| `published_count` | integer | Number of published pipelines. |
| `artifact_count` | integer | Number of artifact history rows. |
| `pipelines` | object\[] | Legacy combined list (published + artifact rows). |
| `count` | integer | Total rows in `pipelines`. |
| `note` | string | Explains published vs. artifact history and that drafts are not visible via the API. |

When `runnable_only=true`, the response contains only `published_pipelines`, `count`, and `note` (upload history omitted).

`UPLOAD_ARTIFACT` response details (success):

| Response field | Type | Description |
| - | - | - |
| `published_files` | string\[] | Bundle paths published in this call. |
| `evicted_pipelines` | string\[] | Previously published pipelines no longer in the bundle after this publish. Non-empty means something was unpublished. |
| `warning` | string | Present when `evicted_pipelines` is non-empty — explains that the bundle was replaced. |
| `eviction_check` | string | Present when the pre-publish lookup failed; verify with `LIST_PIPELINES`. |

Example:

```python theme={null}
# Discover which Matillion connections are configured (no client needed)
matillion_connector(action="LIST_CONNECTIONS")
# result["connections"] → [{"connection_id": "matillion.production", "base_url": "https://app.matillion.com", "is_default": true}]
# result["count"] → 1
```

```python theme={null}
# Run history across all projects
result = matillion_connector(action="LIST_EXECUTIONS")
# result["status_counts"] → e.g. {"SUCCESS": 12, "FAILED": 1}
# result["failed_count"] → 1  (0 means no errors in the returned window)
```

```python theme={null}
# Failed runs in one project, up to 50 rows
matillion_connector(
    action="LIST_EXECUTIONS",
    project_id="<project-id>",
    status_filter="FAILED",
    limit=50,
)
```

```python theme={null}
# What can I run right now? (published bundle only)
matillion_connector(
    action="LIST_PIPELINES",
    project_id="<project-id>",
    environment_name="default",
    runnable_only=True,
)
```

```python theme={null}
# Publish multiple pipelines as one bundle (recommended)
matillion_connector(
    action="UPLOAD_ARTIFACT",
    project_id="<project-id>",
    yaml_repo_id="pharma_matillion",
    yaml_file_paths=["silver/*.yaml", "silver_v2/*.yaml"],
    environment_name="default",
)
# Check result["evicted_pipelines"] — non-empty means prior pipelines were dropped
```

```python theme={null}
# Single-file publish from a Genesis git repo
matillion_connector(
    action="UPLOAD_ARTIFACT",
    project_id="<project-id>",
    artifact_path="gold/summary.tran.yaml",
    yaml_repo_id="pharma_matillion",
    yaml_file_path="gold/summary.tran.yaml",
    environment_name="default",
)
```

```python theme={null}
# Fetch one manual section instead of the full ~42KB manual
matillion_connector(action="HELP", section="troubleshooting")
```

<a id="mcp-admin-tools" />

## `mcp_admin_tools`

Connect Databricks Genie spaces and other HTTP MCP servers at runtime without restarting Genesis, list configured runtime MCP servers, and remove them when no longer needed. Genesis registers each remote MCP endpoint as a persistent tool group and exposes its remote tools to the active thread.

These runtime registrations are persisted under the `mcp_servers` configuration
key (type `dict`, default `{}`). The Connections UI also uses this store for
saved **MCP Server** connections; see [MCP server connections](/docs/Setup/Connections#mcp-server-connections)
for authentication modes, shared/private visibility, and interactive sign-in.
All tools in this group require the **`manage_all_connections`** permission.

This group is distinct from the hosted **Genesis MCP Gateway** that exposes Genesis to external MCP clients such as Claude Code. See [Agent Gateways](/docs/Setup/Agent-Gateways) and [Hosted MCP for Claude Code](/docs/deployments/Hosted-MCP-For-Claude-Code) for that outbound integration path.

Grant the `mcp_admin_tools` tool group to agents that should perform these
operations, and ensure a saved **Databricks** connection exists before
connecting Genie spaces. See [Databricks Action Tools](/docs/Genbot-Toolkit/Databricks-Action-Tools)
for workspace connectivity.

Connection parameters accept either a bare connection name (for example `genie_sp`) or the fully qualified form shown in connection listings (for example `databricks.genie_sp`). Genesis normalizes to the bare name before lookup.

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at runtime, so you normally only provide the business parameters below.
</Tip>

### `list_genie_spaces`

List Databricks Genie spaces visible through a stored Databricks connection. Use this before `add_genie_space` when the user does not know a space ID.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `databricks_connection` | string | none | Required. Name of the saved Databricks connection whose Genie spaces should be listed. |

| Response field | Type | Description |
| - | - | - |
| `success` | boolean | Whether the Databricks API call succeeded. |
| `spaces` | object\[] | Each entry has `id` and `title`. |
| `count` | integer | Number of spaces returned. |
| `databricks_connection` | string | Normalized connection name used for the request. |
| `status_code` | integer | HTTP status from the Databricks Genie spaces API on success. |

### `add_genie_space`

Connect one Databricks Genie space as live MCP tools for the current thread. Genesis builds the Genie MCP URL from the workspace host and space ID, mints a bearer token from the stored Databricks connection, and registers the remote tools.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `databricks_connection` | string | none | Required. Saved Databricks connection used to mint the Genie API bearer token. |
| `space_id` | string | none | Required. Databricks Genie space ID to expose as runtime MCP tools. |
| `name` | string | `""` | Optional MCP tool group name. Defaults to `genie_<space_id>`; unsafe characters are converted to underscores. |

| Response field | Type | Description |
| - | - | - |
| `success` | boolean | Whether registration succeeded. |
| `name` | string | Registered MCP tool group name. |
| `url` | string | Genie MCP HTTP endpoint Genesis connected to. |
| `tools` | string\[] | Registered tool names. |
| `activated` | boolean | Whether this thread's active tool groups were updated. |
| `hint` | string | Next user-facing step when registration succeeds. |

### `add_mcp_server`

Connect a generic HTTP MCP server as live tools without restarting Genesis. Prefer `add_genie_space` for Databricks Genie spaces because it constructs the correct Genie MCP URL from a space ID.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `url` | string | none | Required. HTTP MCP server URL to register at runtime. |
| `auth_connection` | string | none | Required. Stored Genesis connection name used to mint bearer tokens for the HTTP MCP server. |
| `name` | string | none | Required. MCP tool group name to register. Use letters, digits, underscores, or hyphens. |
| `connection_type` | string | `databricks` | Connection type for auth. Currently only `databricks` is supported. |
| `desc` | string | `""` | Optional human-readable description for the MCP tool group. |
| `headers` | object | `null` | Optional non-secret HTTP headers to send when listing and calling the MCP server. |

| Response field | Type | Description |
| - | - | - |
| `success` | boolean | Whether registration succeeded. |
| `message` | string | Registration summary or error detail. |
| `tools` | string\[] | Registered tool names. |
| `activated` | boolean | Whether this thread's active tool groups were updated. |
| `name` | string | Registered MCP tool group name. |

### `list_mcp_servers`

List runtime HTTP MCP servers persisted in Genesis. Tokens and resolved credentials are never returned.

| Response field | Type | Description |
| - | - | - |
| `success` | boolean | Always `true` when permitted. |
| `servers` | object\[] | Each entry includes `name`, `url`, `auth_connection`, `desc`, and `enabled`. |
| `count` | integer | Number of persisted servers. |

### `remove_mcp_server`

Remove a runtime HTTP MCP server and its live tools from the registry.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `name` | string | none | Required. Runtime MCP server or tool group name to remove. |

| Response field | Type | Description |
| - | - | - |
| `success` | boolean | Whether removal completed without tool-removal failures. |
| `removed` | string\[] | Tool names removed from the registry. |
| `failed` | string\[] | Tool names that could not be removed. |
| `message` | string | Human-readable removal summary. |

### Typical Genie workflow

```text theme={null}
list_genie_spaces(databricks_connection="analytics")
add_genie_space(databricks_connection="analytics", space_id="<space-id>")
list_mcp_servers()
remove_mcp_server(name="genie_<space-id>")
```

<Note>
  After `add_genie_space` or `add_mcp_server` succeeds, the user can ask natural-language data questions against the connected Genie space or remote MCP tools. If registration fails, verify the Databricks connection, space ID, workspace permissions, and that the caller holds `manage_all_connections`.
</Note>

<a id="onedrive-tools" />

## `onedrive_tools`

Microsoft OneDrive personal-drive operations via Microsoft Graph API. This tool is not for SharePoint site URLs or SharePoint Connections; use [`sharepoint_tools`](#sharepoint-tools) for SharePoint content. See [Microsoft OneDrive](/docs/Setup/Microsoft-OneDrive) for the customer-facing setup and usage path. When the `onedrive` tool runs without a named connection, Genesis resolves the effective default `onedrive` connection for the active agent (**My default**, then **Role default**). Legacy credentials from **Config -> Microsoft OneDrive** apply only when no scoped default resolves.

<a id="outpost-tools" />

## `outpost_tools`

Configure Genesis Outposts: a small program a customer runs inside their own network (a laptop to try it, a VM, Docker or Kubernetes, on AWS, Azure, GCP or on-prem) that dials out to Genesis so it can reach private hosts such as internal databases, Jira or GitLab Data Center, and internal APIs. A connection goes through an Outpost when it is set to **Through a Genesis Outpost**, or when its host matches a domain pattern the Outpost routes (for example `*.corp.internal`). A connection's password or secret can stay in the customer's secret store as `outpost_<outpost>/<secret-name>#<json-field>`. See [Genesis Outposts](/docs/Setup/Outposts-Overview) for setup, security and troubleshooting.

For self-hosted Docker listener behavior and Outpost port availability, see [Genesis on Docker](/docs/deployments/Docker/Genesis-Container-Distribution).

All tools in this group require the **`manage_all_connections`** permission. The in-product skill `outpost-setup` walks an agent through the whole setup.

| Tool | Purpose |
| - | - |
| `list_outposts` | List Outposts, whether the feature is on, and each Outpost's live status (one network round trip per Outpost; pass `include_status=false` to skip). Includes a no-key warning even when live status is skipped. |
| `set_outposts_enabled` | Turn the feature on or off. |
| `save_outpost` | Create an Outpost, or change the domain patterns it routes and the roles allowed to route connections through it. Refuses a pattern change that would make saved connections reach one host name through multiple Outposts. |
| `remove_outpost` | Remove an Outpost. |
| `check_outpost_route` | From inside the customer network, check the Outpost's allowlist, DNS and a TCP connection to a host and port. |
| `explain_outpost_routing` | Say which Outpost, if any, a connection type and location would be routed through; reports a diagnosis when multiple Outposts claim the host name. |
| `get_outpost_install_instructions` | Produce the key-pair commands, Snowflake SQL, `docker run` command and Kubernetes environment for installing an Outpost. |

`save_outpost` creates the definition but does not issue its tunnel key. After creating an
Outpost, open **Config -> Outposts -> Install** and choose **New tunnel key**; Genesis shows
the key once. See [Each Outpost's tunnel key](/docs/Setup/Outposts-Install#each-outposts-tunnel-key)
for the setup and migration behavior.

`list_outposts` includes `tunnel_key_warning` when Genesis has not issued an Outpost a tunnel
key, even when `include_status=false`. Relay the warning as written; it says the Outpost cannot
sign in and how to issue its key. For a `key_refused` diagnosis, see
[Outpost Troubleshooting](/docs/Setup/Outposts-Troubleshooting#diagnoses).

When the Snowflake Native App does not expose the Outpost tunnel endpoint, `list_outposts`
reports the feature as disabled, and `set_outposts_enabled` with `enabled=true` and
`get_outpost_install_instructions` fail with the reason Outposts are unavailable; relay that
reason as written and do not retry. Native App support is version-dependent; see
[Genesis Outposts](/docs/Setup/Outposts-Overview) for availability.

### `outpost_tools` parameters

| Tool | Parameter | Type | Default | Description |
| - | - | - | - | - |
| `list_outposts` | `include_status` | boolean | `true` | Contact each Outpost for live status; one network round trip per Outpost, up to 10 seconds each if one is down. Set `false` to list configuration without contacting them. |
| `set_outposts_enabled` | `enabled` | boolean | Required | Turn Outpost routing on or off. |
| `save_outpost` | `outpost_name` | string | Required | Lowercase letters, digits, or `-`, starting with a letter or digit; up to 63 characters. |
| `save_outpost` | `serves` | string\[] \| null | `null` | Optional host patterns such as `*.corp.internal`; replaces the current list when supplied. Omit to keep it. |
| `save_outpost` | `route_roles` | string\[] \| null | `null` | Optional RBAC roles allowed to route through this Outpost, besides admins. Replaces the current list when supplied; `[]` leaves access to admins. |
| `remove_outpost` | `outpost_name` | string | Required | Name of the Outpost to remove. Removing its definition does not stop the customer-run process. |
| `check_outpost_route` | `outpost_name` | string | Required | Name of the Outpost to test. |
| `check_outpost_route` | `host` | string | Required | Private hostname or IP address to test from the customer network. |
| `check_outpost_route` | `port` | integer | Required | TCP port on the destination host. |
| `explain_outpost_routing` | `connection_type` | string | Required | Connection type, such as `postgres`, `mssql`, or `jira`. |
| `explain_outpost_routing` | `locator` | object | Required | Non-secret location fields, such as `{"host":"db.corp.internal","port":5432}`. Do not include passwords or tokens. |
| `get_outpost_install_instructions` | `outpost_name` | string | Required | Name of an existing Outpost. |
| `get_outpost_install_instructions` | `target` | string | `docker` | Install target: `laptop`, `vm`, `docker`, or `kubernetes`. |
| `get_outpost_install_instructions` | `host_os` | string \| null | `null` | For `laptop` or `vm`: `linux`, `macos` (laptop only), or `windows`. |
| `get_outpost_install_instructions` | `arch` | string \| null | `null` | For `laptop` or `vm`: `amd64` or `arm64`. |
| `get_outpost_install_instructions` | `namespace` | string \| null | `null` | Kubernetes namespace; defaults to `genesis-outpost` in the generated instructions. |
| `get_outpost_install_instructions` | `allowed_destinations` | string\[] \| null | `null` | Optional `host:port` destinations for the Outpost's `ALLOWED_DESTINATIONS` list. |

For example, check whether a database locator would use an Outpost before
creating its connection:

```json theme={null}
{
  "connection_type": "postgres",
  "locator": {"host": "db.corp.internal", "port": 5432}
}
```

Pass those fields to `explain_outpost_routing`; it returns the selected Outpost
or says that the connection will be reached directly. See [Connect a system through an Outpost](/docs/Setup/Outposts-Connect-Systems)
for the dashboard flow.

<a id="power-bi-tools" />

## `power_bi_tools`

Browse Microsoft Power BI workspaces, inspect reports, check dataset refresh
history, trigger refreshes, and update dataset data-source bindings or
parameters. This group uses the effective default `power_bi` connection for the
current user (My default, then Role default) from
[Connections](/docs/Setup/Connections) unless you pass a specific `connection`.

Grant agents the `power_bi_tools` tool group and a saved Power BI connection
before calling these actions.

### `power_bi_connector`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `LIST_WORKSPACES`, `LIST_REPORTS`, `GET_REFRESH_STATUS`, `TRIGGER_REFRESH`, `UPDATE_DATASOURCES`, or `UPDATE_PARAMETERS`. |
| `connection` | string | `null` | Optional connection name such as `power_bi.production`. If omitted, Genesis uses the effective default `power_bi` connection for the current user. |
| `workspace_id` | string | `null` | Power BI workspace (group) ID. Required for every action except `LIST_WORKSPACES`. |
| `dataset_id` | string | `null` | Power BI dataset ID. Required for `GET_REFRESH_STATUS`, `TRIGGER_REFRESH`, `UPDATE_DATASOURCES`, and `UPDATE_PARAMETERS`. |
| `update_details` | array | `null` | List of update objects for `UPDATE_DATASOURCES` or `UPDATE_PARAMETERS`. For `UPDATE_DATASOURCES`, each entry needs `datasourceSelector` and `connectionDetails`. For `UPDATE_PARAMETERS`, each entry needs `name` and `newValue`. |
| `top` | integer | `10` | Maximum refresh-history entries for `GET_REFRESH_STATUS`. Genesis clamps this between `1` and `100`. |

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at runtime, so you normally only provide the business parameters above.
</Tip>

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `LIST_WORKSPACES` | List Power BI workspaces (groups). | none |
| `LIST_REPORTS` | List reports in a workspace. | `workspace_id` |
| `GET_REFRESH_STATUS` | Return the latest refresh plus refresh history for a dataset. | `workspace_id`, `dataset_id` |
| `TRIGGER_REFRESH` | Start a dataset refresh. | `workspace_id`, `dataset_id` |
| `UPDATE_DATASOURCES` | Update dataset data-source bindings (for example after an upstream connection change). | `workspace_id`, `dataset_id`, `update_details` |
| `UPDATE_PARAMETERS` | Update parameterized dataset configuration. | `workspace_id`, `dataset_id`, `update_details` |

Successful responses include `success: true` plus action-specific fields:
`workspaces` for `LIST_WORKSPACES`, `reports` for `LIST_REPORTS`,
`latest_refresh` and `refresh_history` for `GET_REFRESH_STATUS`, and `message`
for write operations. When no effective default Power BI connection exists for
the current user, Genesis returns an error directing you to **Config ->
Connections**. When multiple role defaults conflict, pass `connection` explicitly
or set a user default.

Example:

```python theme={null}
# List workspaces on the default connection
power_bi_connector(action="LIST_WORKSPACES")
```

```python theme={null}
# Check refresh history, then trigger a refresh
power_bi_connector(
    action="GET_REFRESH_STATUS",
    workspace_id="<workspace-id>",
    dataset_id="<dataset-id>",
    top=5,
)

power_bi_connector(
    action="TRIGGER_REFRESH",
    workspace_id="<workspace-id>",
    dataset_id="<dataset-id>",
)
```

<a id="openmetadata-tools" />

## `openmetadata_tools`

Search and manage OpenMetadata entities and governance metadata. When
`connection` is omitted on `openmetadata_connector`, Genesis resolves the
effective usable `openmetadata` connection for the current user and active bot
(My default, then Role default). Pass an explicit connection name such as
`openmetadata.prod` when you need a specific saved connection. If no usable
default applies, the tool returns the structured connection-selection response
described in [`connections_action`](/docs/Genbot-Toolkit/Additional-Tool-Groups#connections-action-tools).

See [OpenMetadata](/docs/Setup/OpenMetadata) for the customer-facing setup and governance usage path.

### `openmetadata_connector`

Use `ADD_TAGS` or `REMOVE_TAGS` to apply or remove classification tags on an
OpenMetadata entity or one of its columns. These actions find a column by name
or fully-qualified name, so you do not need to calculate its position in the
entity's columns array.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Use `ADD_TAGS` to add classification tags or `REMOVE_TAGS` to remove them. |
| `connection` | string | `null` | Optional saved OpenMetadata connection name. If omitted, Genesis uses the effective default `openmetadata` connection for the current user. |
| `entity_type` | string | `null` | OpenMetadata entity type. |
| `entity_id` | string | `null` | OpenMetadata entity ID. Provide this or `fully_qualified_name`. |
| `fully_qualified_name` | string | `null` | Fully-qualified name of the entity. Provide this or `entity_id`. |
| `tags` | string | `null` | Required for `ADD_TAGS` and `REMOVE_TAGS`. Comma-separated classification tag names, such as `PII.Sensitive,Tier.Tier1`. |
| `column` | string | `null` | Optional column name or fully-qualified name. Omit it to tag the entity itself. |
| `timeout_seconds` | integer | `30` | HTTP timeout in seconds. |

Adding a tag preserves existing tags and adding the same classification tag
twice does nothing. Removing tags affects only the classification tags named
in `tags`; glossary-term tags are left unchanged, even when their names match.
Use `UPDATE_ENTITY` with `method=PATCH` to attach a glossary term with
`source` set to `Glossary`.

When the requested tags already match the current state, the response includes
`changed: false` and no write occurs. Tag updates read the current list and
replace it with the merged list, so a tag added by another writer between the
read and write can be overwritten.

Examples:

```python theme={null}
# Add a classification tag to a column by name
openmetadata_connector(
    action="ADD_TAGS",
    entity_type="table",
    fully_qualified_name="analytics.customers",
    column="GOVT_ID",
    tags="PII.Sensitive",
)

# Remove a classification tag from the entity itself
openmetadata_connector(
    action="REMOVE_TAGS",
    entity_type="table",
    entity_id="<entity-id>",
    tags="Tier.Tier1",
)
```

<a id="railway-tools" />

## `railway_tools`

Railway-backed runtime choices are documented in [Sandbox Sessions](/docs/User-Guide/Sandbox-Sessions).

### `railway_action`

Use this function to inspect available Railway connections, list projects, retrieve project inventory, manage environment variables, trigger deploys, and run GraphQL passthrough operations.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `LIST_CONNECTIONS`, `LIST_PROJECTS`, `GET_PROJECT_INVENTORY`, `SET_ENV_VARS`, `TRIGGER_DEPLOY`, `GET_DEPLOYMENT_STATUS`, or `GRAPHQL_PASSTHROUGH`. |
| `credential_name` | string | `null` | Optional Genesis Railway connection name (`type=railway`). When omitted, Genesis resolves the caller's scoped default **Railway** connection (**My default**, then **Role default**). |
| `token` | string | `null` | Optional explicit Railway token. Prefer `credential_name` when possible. |
| `project_id` | string | `null` | Railway project ID. Required for `GET_PROJECT_INVENTORY` and `SET_ENV_VARS`. |
| `service_id` | string | `null` | Railway service ID. Required for `SET_ENV_VARS`, `TRIGGER_DEPLOY`, and `GET_DEPLOYMENT_STATUS`. |
| `environment_id` | string | `null` | Railway environment ID. Required for `SET_ENV_VARS`, `TRIGGER_DEPLOY`, and `GET_DEPLOYMENT_STATUS`. |
| `variables` | object | `null` | Environment-variable map for `SET_ENV_VARS`. |
| `query` | string | `null` | GraphQL query or mutation for `GRAPHQL_PASSTHROUGH`. |
| `graphql_variables` | object | `null` | GraphQL variables for `GRAPHQL_PASSTHROUGH`. |
| `timeout_sec` | integer | `10` | Optional GraphQL request timeout in seconds. |

Railway auth can resolve from `credential_name`, an explicit `token`, or environment variables `RAILWAY_TOKEN` and `RAILWAY_API_TOKEN`. For Railway-backed sandbox and terminal flows, Genesis keeps the auth mode that passed its live SSH check so reconnects reuse the verified credentials.

Example:

```text theme={null}
railway_action(action="LIST_PROJECTS", credential_name="railway-prod")
```

<a id="remote-app-deploy-tools" />

## `remote_app_deploy_tools`

Set up Snowflake SPCS ingress access for remote apps, deploy Genesis Apps to
external sandboxes, tear them down, and check remote health.

### `remote_app_deploy_action`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `setup_spcs_access`, `deploy`, `undeploy`, or `status`. |
| `app_id` | string | `""` | Required for `deploy`, `undeploy`, and `status`. Genesis App ID to operate on. |
| `backend` | string | `""` | Required for `deploy`. Deployment backend: `railway`, `eks`, or `docker`. |
| `backend_options` | string | `""` | Optional JSON string of backend-specific options such as project or namespace settings. |
| `service_user_name` | string | `"genesis_remote_app_svc"` | For `setup_spcs_access`: Snowflake service user Genesis creates or updates for remote app ingress. |
| `service_role_name` | string | `"genesis_remote_app_role"` | For `setup_spcs_access`: Snowflake role Genesis creates or updates for the service user. |
| `spcs_service_role` | string | `""` | Optional fully qualified Snowflake service role to grant during `setup_spcs_access`, such as `db.schema.service!endpoint_role`. |
| `confirm_identity_delegation` | string | `""` | Required for `deploy`. Must be `"true"` after the user acknowledges that the remote app will use the current caller's Genesis identity and permissions. |
| `user_id` | string | implicit | Injected from the requesting user context. `deploy` uses this delegated user identity to mint `GENESIS_APP_TOKEN`; empty identities are rejected. |

`bot_id` and `thread_id` are also injected implicitly from the active tool
context and do not normally need to be supplied manually.

<Note>
  Remote deployments mint `GENESIS_APP_TOKEN` for the delegated caller
  identity, so remote apps can keep calling Genesis APIs with
  `X-Genesis-App-Token` when platform auth is enabled.
</Note>

`status` queries the live deployment backend when possible. Its response can include the resolved URL, `URL Type` (such as `external` or `cluster_internal`), backend status, ready replica counts, and health-check results.

Example:

```text theme={null}
remote_app_deploy_action(
  action="deploy",
  app_id="revenue-dashboard",
  backend="eks",
  backend_options="{}",
  confirm_identity_delegation="true"
)

remote_app_deploy_action(action="status", app_id="revenue-dashboard")
```

<a id="palantir-foundry-app-tools" />

## `palantir_foundry_app_tools`

Prove that a GenesisApp rebuilt from a Foundry Workshop app displays the same
values as the Workshop app. Assign this group alongside `palantir_foundry_tools`,
then build the app from `foundry_describe_app`'s spec and land its ontology
tables in Databricks. For the migration workflow and verdict meanings, see
[Migrating and proving a Workshop app](/docs/Integrations/Palantir-Foundry/Palantir-Foundry#migrating-and-proving-a-workshop-app).

### `foundry_prove_app`

Compares each displayed value, compiled chart layer, pivot table, and object table
from Foundry's Ontology API with the rebuilt app for supplied or randomly sampled
inputs. The result includes `passed`, a verdict `summary`, mismatches in
`findings`, unsupported values and widgets in `not_covered`, rendered-page checks,
the inputs and random `seed`, and a `proof_file` containing every check. For
mismatch diagnosis and verdict meanings, see the integration guide.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `connection_id` | string or null | `null` | Foundry connection holding the Workshop app; omitted uses the default connection. |
| `module_rid` | string | `""` | Required Workshop module RID used to build the app spec. |
| `app_id` | string | `""` | Required GenesisApp ID to prove. |
| `databricks_connection_id` | string | `""` | Databricks connection for mismatch diagnosis; required when `app_url` points to a Databricks App, and must use a service-principal OAuth connection that can access the app. |
| `target_catalog` | string | `""` | Required catalog containing the landed ontology tables. |
| `target_schema` | string | `""` | Required schema containing the landed ontology tables. |
| `ontology` | string | `""` | Ontology API name; omitted lets Genesis resolve it from the app's object types. |
| `version` | string or null | `null` | Published Workshop app version; omitted selects the newest. |
| `parameter_values` | array of objects, string, or null | `null` | Inputs keyed by the spec's parameter names. An object parameter takes its primary key. Omit to sample from Foundry; a JSON string is also accepted. |
| `samples` | integer | `3` | Number of random inputs when `parameter_values` is omitted; clamped to 1–10. |
| `seed` | integer or null | `null` | Random seed. Reuse the returned seed and `parameter_values` to repeat a proof. |
| `app_url` | string | `""` | HTTPS URL of a rebuilt app running outside Genesis, such as a Databricks App. Omit to prove the GenesisApp identified by `app_id`. |

```python theme={null}
foundry_prove_app(
    connection_id="palantir_foundry.aviation",
    module_rid="ri.workshop.main.module.<module-id>",
    app_id="aviation-overview",
    target_catalog="main",
    target_schema="foundry_ontology",
    samples=3,
    seed=42,
)
```

`bot_id`, `thread_id`, and `user_id` are injected from the active tool context.
The proof can make multiple Foundry and app requests per input. See the integration
guide for end-to-end cost and deployed-app behavior.

<a id="rbac-action-tools" />

## `rbac_action_tools`

Automate role, permission, and access-governance tasks. For the administrative model and governance guidance, see [Users and Roles](/docs/Setup/Users-And-Roles) and [RBAC Practical Guide](/docs/Security-Controls/RBAC-Practical-Guide).

### `rbac_action`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Use read actions such as `GET_USERS_WITH_ROLE`, `GET_ROLE_AGENT_ACCESS`, and `GET_AGENT_ROLE_ACCESS` to inspect RBAC assignments from chat. |
| `role_name` | string | `null` | Required for `GET_USERS_WITH_ROLE` and `GET_ROLE_AGENT_ACCESS`. Role identifier to inspect. |
| `agent_id` | string | `null` | Required for `GET_AGENT_ROLE_ACCESS`. Agent identifier to inspect. |
| `target_user_id` | string | `null` | Target user ID or email for user-related operations such as `GET_USER_ROLES`, `ASSIGN_ROLE`, `CHECK_USER_PERMISSION`, and `CHECK_TOOL_ACCESS`. If an email belongs to multiple users, the action is refused and returns the matching user IDs; retry with the intended user's ID. |

<Note>
  Read actions validate identifiers before returning data. When `role_name` or `agent_id` does not exist, `rbac_action` returns `success: false` with an `error` message instead of an empty success payload. Role and agent lookups can include `Did you mean: ...?` suggestions when Genesis finds close matches.

  Successful write actions (`ASSIGN_ROLE`, `REVOKE_ROLE`, and other mutating actions in this tool group) also append rows to `ADMIN_AUDIT_LOG` with `source=bot` and the acting bot ID as `actor_user_id`. See [RBAC Practical Guide → Admin audit log](/docs/Security-Controls/RBAC-Practical-Guide#admin-audit-log).
</Note>

Example:

```text theme={null}
rbac_action(action="GET_USERS_WITH_ROLE", role_name="analyst")
rbac_action(action="GET_ROLE_AGENT_ACCESS", role_name="analyst")
rbac_action(action="GET_AGENT_ROLE_ACCESS", agent_id="eve")
```

<a id="sandbox-tools" />

## `sandbox_tools`

Provision and operate sandbox execution environments, then run commands,
install dependencies, move files, and inspect results. This is also the
preferred first tool group for AWS infrastructure analysis, EKS/Kubernetes,
Helm, `kubectl`, AWS CLI, `boto3`/AWS SDK, cloud deployment, and cloud
monitoring tasks.

### `sandbox_action`

Use `sandbox_action` for long-running image builds and registry readiness
checks when you need a polling-friendly status contract.

For EKS/K8s backends, Genesis injects AWS credentials from the caller's scoped
default **AWS** connection when `credential_name` is omitted from
`backend_options`. For Railway-backed flows, Genesis resolves the caller's
scoped default **Railway** connection when no explicit `credential_name` is
provided. Jenkins image builds resolve the scoped default **jenkins**
connection the same way. See [Default connection layers](/docs/Setup/Connections#default-connection-layers).

<Note>
  For EKS/K8s work, prefer `backend="eks"` or `backend="k8s"` with a saved
  `target_env` when possible, or include explicit `backend_options` plus
  `credential_name` so cluster auth does not depend on a kubeconfig in the
  Genesis application container. The packaged guidance skill for this workflow
  is `aws-eks-sandbox-operations`; the older
  `deploy-helm-chart-eks` name remains a compatibility alias.
</Note>

#### Default backend

The `backend` parameter defaults to `"local"`. When the operator configures
`sandbox.default_backend` (for example via Helm `sandbox.defaultBackend` on
EKS, `GENESIS__SANDBOX__DEFAULT_BACKEND`, `GENESIS_SANDBOX_DEFAULT_BACKEND`,
or `sandbox.default_backend` in `genesis-config.yaml`), calls that omit
`backend` or pass `backend="local"` automatically resolve to that configured
default (for example `"eks"` on EKS deployments). Explicit `backend` values
other than `"local"` are always honored.

In a Databricks App, `local` is unavailable because it starts Docker on the
Genesis host. It is omitted from the backend list and an explicit local start is
refused; choose a remote backend instead.

#### Azure Container Instances

Set `backend="azure_aci"` to run a Linux sandbox in Azure Container Instances in the customer's
own Azure subscription. For what it is, setup, everyday use and error messages, see
[Azure Sandboxes](/docs/Setup/Azure-Sandboxes-Overview),
[Set Up Azure Sandboxes](/docs/Setup/Azure-Sandboxes-Setup),
[Use Azure Sandboxes](/docs/Setup/Azure-Sandboxes-Using) and
[Azure Sandbox Troubleshooting](/docs/Setup/Azure-Sandboxes-Troubleshooting).

Each sandbox is one container group (`genesis-sbx-<id>`) with one container. `start` waits for the
group to run (about 25 to 30 seconds with the default image, up to 10 minutes), and `stop` deletes
it. The container's main process sleeps for the session's `max_lifetime_minutes` (default 480)
with restart policy `Never`, so it exits and stops billing even if Genesis is down; the sandbox
monitor also stops sessions past their idle timeout (default 30 minutes for an agent start) or
maximum lifetime. Each command adds about two seconds of overhead; its output is
SHA-256-verified end to end.

For Azure sessions, output from sandbox tool commands is also mirrored into the session's
terminal history, alongside interactive terminal activity.

`start` requires a saved Genesis Azure connection: `credential_name` in `backend_options`, or the
caller's **My default**, then **Role default**. Inline `tenant_id`, `client_id` or
`client_secret` in `backend_options` is refused, because the session must be reattached and
deleted as the same identity after a restart. Connection access is checked as the calling user
and agent. A started sandbox stays bound to the connection, subscription, resource group and
region it resolved.

Run `check_backend_connection` with `backend="azure_aci"` before starting. It requests a token
from Microsoft Entra ID, reads the resource group, and reads the principal's effective
permissions there to confirm container-group read, write, delete and exec (one token request and
two Azure Resource Manager calls). `list_backend_connections` with this backend lists the Azure
connections the caller can use.

When `image` is omitted or is `python:3.11-slim`, Genesis pulls
`mcr.microsoft.com/mirror/docker/library/python:3.11-slim`, because Docker Hub throttles
anonymous pulls from Container Instances. Any other image is used as given; it must be Linux and
provide `/bin/sh`, `base64`, `sha256sum`, `cat`, `cut`, `wc`, `cp`, `dd`, `tr`, `mkdir` and `rm`.

| `backend_options` key | Type | Default | Description |
| - | - | - | - |
| `credential_name` | string | caller's default Azure connection | Saved Genesis Azure connection to use. |
| `subscription_id` | string | connection value | Subscription override. |
| `resource_group` | string | connection value | Resource group override. |
| `location` | string | connection's Region, else `eastus` | Azure region override. On SPCS, egress is approved only for the connection's own region. |
| `cpu_cores` | number | `1.0` | Container CPU request in vCPUs. |
| `memory_gb` | number | `1.5` | Container memory request in GB. |
| `subnet_id` | string | none | Azure subnet resource ID for VNet attachment. The subnet must be delegated to `Microsoft.ContainerInstance/containerGroups`. |
| `registry_server` | string | none | Private image registry hostname, for example `myregistry.azurecr.io`. |
| `registry_username` | string | none | Username when the private registry requires authentication. |
| `registry_password` | string | none | Password or token when the private registry requires authentication. |

Genesis must reach `login.microsoftonline.com:443`, `management.azure.com:443` and the exec
WebSocket host `*.<region>.atlas.cloudapp.azure.com:19390`; see
[Allow Genesis to reach Azure](/docs/Setup/Azure-Sandboxes-Setup#allow-genesis-to-reach-azure).

For example, start a sandbox in a specific saved connection:

```text theme={null}
sandbox_action(
  action="start",
  backend="azure_aci",
  backend_options={"credential_name": "azure-prod", "cpu_cores": 2, "memory_gb": 4}
)
```

#### Repository file transfers

Use the repository transfer actions when a sandbox needs files from a Genesis
Git repository or when a downloaded sandbox file must be saved back to one.

| Action | Purpose and constraints |
| - | - |
| `upload_file_from_repo` | Copy a repository file into the sandbox as UTF-8 text. When `repo_id="uploads"`, the path is resolved from the current thread and binary files are rejected; use a binary transfer action for non-text files. |
| `upload_artifact_from_repo` | Copy a repository file into the sandbox without decoding it, preserving binary content. |
| `upload_mission_artifact_from_repo` | Copy a binary artifact from the repository belonging to the current Mission. Requires the current thread context and rejects a `repo_id` that is not that Mission's repository. |
| `download_file` with `repo_id` | Read the sandbox file as exact bytes and save it to the repository path supplied by `repo_file_path`. Use this form for binary files; without `repo_id`, the action keeps its normal text-oriented response. |

For repository-backed transfers, provide repository-relative paths only. A
Mission-restricted upload uses the complete Mission repository id, not the
`uploads` repository used for incoming chat attachments.

[Sandbox transfer notes](/docs/deployments/Databricks/Genesis-On-Databricks#durable-chat-uploads).

#### `action="check_image_tag"`

Check whether a tag manifest is available in a registry before starting a deployment or waiting on a build to publish.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Use `check_image_tag` to perform a single manifest check. |
| `registry` | string | `ghcr.io` | Registry hostname for the manifest lookup. |
| `repository` | string | none | Required. Image repository path such as `genesis-computing-ai/genesis`. |
| `tag` | string | `latest` | Image tag to check. |
| `registry_username` | string | `null` | Optional username for authenticated registry checks. |
| `registry_password` | string | `null` | Optional password or token for authenticated registry checks. |
| `registry_token` | string | `null` | Optional bearer token for authenticated registry checks. |

| Response field | Type | Description |
| - | - | - |
| `status` | string | Readiness result: `ready`, `not_ready`, `timeout`, or `error`. |
| `ready` | boolean | `true` when the manifest is available. |
| `http_status` | integer | Manifest request status when the registry returns one. |
| `tool_result_status` | string | `running` when the tag is not ready yet, `completed` when it is ready, or `failed` on timeout or error. |
| `next_poll_seconds` | integer | Suggested delay before the next check when `tool_result_status` is `running`. |
| `guidance` / `warnings` | array | Registry-specific auth or readiness hints. |

Example:

```text theme={null}
sandbox_action(
  action="check_image_tag",
  registry="ghcr.io",
  repository="genesis-computing-ai/genesis",
  tag="dev"
)
```

`wait_for_image_tag` uses the same registry and auth parameters, then adds `poll_interval_seconds` (number, default `30`) and `poll_timeout_seconds` (number, default `900`) for automatic polling. Long-running `build_image` and `get_build_status` calls follow the same `tool_result_status` and `next_poll_seconds` contract while a build is still in progress.

<a id="sandbox-spec-tools" />

## `sandbox_spec_tools`

Save and manage reusable sandbox specifications such as target environments, security profiles, and container definitions.

### `sandbox_env`

Use this function to save and validate reusable sandbox specs, target environments, and security profiles, including Railway-backed target-environment planning and apply flows.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. Includes `list_target_envs`, `get_target_env`, `save_target_env`, `delete_target_env`, `validate_target_env`, `list_security_profiles`, `get_security_profile`, `save_security_profile`, `delete_security_profile`, `validate_security_profile`, `railway_token_info`, `railway_list_projects`, `railway_get_project_inventory`, `railway_plan_target_env`, and `railway_apply_target_env`. |
| `target_env_name` | string | `null` | Target environment profile name for the target-environment actions. |
| `security_profile_name` | string | `null` | Security profile name for the security-profile actions. |
| `credential_name` | string | `null` | Saved Genesis connection name used for backend auth, such as a Railway connection. Required for `railway_apply_target_env` so later runs can resolve Railway auth from the saved target environment. |
| `apply` | boolean | `false` | For apply actions, set `true` to create resources or save generated artifacts. |
| `dry_run` | boolean | `true` | Planning-only mode. Set `false` only when you want the action to mutate external systems. |

Railway planning and apply actions also accept `workspace`, `project_id` or `project_name`, `service_id` or `service_name`, `environment_id` or `environment_name`, `create_project_name`, `create_service_name`, `create_environment_name`, and `image` when you need to discover, select, or create the target resources.

Example:

```text theme={null}
sandbox_env(
  action="railway_apply_target_env",
  target_env_name="railway-analytics",
  credential_name="railway-prod",
  project_name="analytics-runtime",
  service_name="worker",
  environment_name="production",
  apply=true,
  dry_run=false
)
```

<a id="sharepoint-tools" />

## `sharepoint_tools`

Read-only SharePoint Online file operations via Microsoft Graph API with per-user OAuth. Genesis resolves an omitted `connection_name` only when the effective `sharepoint` connection is usable by the requesting user and active bot; otherwise it returns the structured connection-selection response described in [`connections_action`](/docs/Genbot-Toolkit/Additional-Tool-Groups#connections-action-tools). See [SharePoint](/docs/Setup/SharePoint) for OAuth provider and connection setup.

If an operation using an omitted `connection_name` fails after Genesis selected the effective default, and another accessible candidate includes a warning-free option, the response also includes `connection_recovery`. It preserves the original `error` and provides the failed `failed_connection_id`, the default `selected_source`, alternative connection summaries in `alternatives`, and `retry.tool_parameter = "connection_name"`. Preserve the original error and ask the user which alternative to use; Genesis does not retry automatically. Explicitly named connection failures do not trigger this recovery response.

### `sharepoint`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `TEST_CONNECTION`, `LIST_DRIVES`, `LIST`, `DOWNLOAD_FILE`, or `GET_METADATA`. |
| `connection_name` | string | `null` | SharePoint connection name. When omitted, Genesis uses the effective default `sharepoint` connection for the current user. |
| `drive_id` | string | `null` | Document library (drive) ID from `LIST_DRIVES`. Required for `LIST`, `DOWNLOAD_FILE`, and `GET_METADATA`. |
| `folder_path` | string | `/` | Path within a document library relative to the drive root (e.g. `LPs` or `Fund level/SCALE`). Default `/` lists the drive root. Alias: `path`. |
| `item_id` | string | `null` | File or folder ID from `LIST` or `GET_METADATA`. For `LIST`, pass a folder's id to list that folder's children; takes precedence over `folder_path`. Required for `DOWNLOAD_FILE` and `GET_METADATA`. |
| `destination_path` | string | `null` | Destination path within a Git repository for downloads (e.g. `downloads/file.pdf` or `downloads/` to keep the original filename). |
| `repo_id` | string | `null` | Git repository ID for `DOWNLOAD_FILE`. |

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at runtime, so you normally only provide the business parameters above.
</Tip>

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `TEST_CONNECTION` | Verify access by resolving the configured SharePoint site. | none |
| `LIST_DRIVES` | List document libraries on the connected site. | none |
| `LIST` | List files and folders in a document library. | `drive_id` |
| `DOWNLOAD_FILE` | Download a file into a Git repository. | `drive_id`, `item_id`, `repo_id` |
| `GET_METADATA` | Get metadata for a file or folder. | `drive_id`, `item_id` |

### Listing folders

For `LIST`, Genesis selects the folder to browse in this order:

1. **`item_id`** — a folder DriveItem id (from a prior `LIST` or `GET_METADATA`); lists that folder's children.
2. **`folder_path`** (or alias **`path`**) — a path relative to the drive root (e.g. `Reports/2024`). `/` or omitted lists the drive root.
3. With neither `item_id` nor `folder_path`/`path`, Genesis lists the drive root.

Successful `LIST` responses echo the selector Genesis honored: `item_id` when listing by id, otherwise `folder_path`.

Example:

```python theme={null}
# List libraries, then browse the drive root
sharepoint(action="LIST_DRIVES")
sharepoint(action="LIST", drive_id="b!xxxx")

# Subfolder by path (folder_path or path)
sharepoint(action="LIST", drive_id="b!xxxx", folder_path="Reports/2024")

# Subfolder by id — takes precedence over folder_path
sharepoint(action="LIST", drive_id="b!xxxx", item_id="01ABC...")
```

<a id="chat-work-tools" />

## `chat_work_tools`

Promote the current Slack, Microsoft Teams, or Google Chat conversation into a tracked work
item on the [Requests](/docs/User-Guide/Work-Center) page. When
`ticket_automation.auto_track_chat_requests` is enabled (the default), accepted
chat messages already create a Request; agents call this tool when the user
explicitly asks to track, log, or follow up on work, or to split separate work
in an already-tracked conversation. When automatic tracking is disabled, this
tool is the only way chat becomes a work item. Correlation stays deterministic
in either mode — there is no heuristic auto-attachment.

### `promote_conversation_to_work`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `title` | string | required | Short work-item title describing the requested work (not the whole conversation). |
| `requested_by` | string | `null` | Fallback display name of the requester. Genesis prefers the platform-authenticated message author from chat ingress; supply this only when that identity is missing. |
| `start_new_item` | boolean | `false` | Set `true` only when the user explicitly asks for separate work in an already-tracked conversation (`track this separately`, `new work item`). Creates a second ledger row and routes future replies to it. |

Returns `{success, work_item_id, provider, created_by, attributed_to_another}` on success, or `{success: false, error}` when called outside a supported chat conversation or when the ledger is unavailable. `created_by` is the creator recorded on the work item, not necessarily the current caller: a repeat promotion keeps the original promoter, and a record with no named creator is returned as `created_by.display: "unattributed"`. `attributed_to_another` is `true` when the record names someone else, `false` when it names the current caller, and `null` when nobody is named or the creator could not be read back. Calling the tool twice for the same conversation is safe and returns the same work item. In automatic tracking mode the conversation may already have a Request, making a repeat call idempotent unless `start_new_item` is `true`.

After promotion, replies in the same Slack thread, Teams channel reply chain
(and quoted replies in Teams chats), or current Google Chat DM episode attach to
the item automatically. Google Chat episodes do not cross a `/new` boundary.

On success Genesis also stores `external_url` on the work item so the
[Requests](/docs/User-Guide/Work-Center) row deep-links back to the chat
message: Slack via a best-effort permalink (`chat.getPermalink` using the bot's
`slack_app_token`), Teams via a `teams.microsoft.com/l/message/...` URL from
tenant, conversation, and activity identifiers. Google Chat does not add an
external URL. Missing tokens, API failures, or incomplete identifiers omit the
link without blocking promotion. Automatic
tracking (`ticket_automation.auto_track_chat_requests`) applies the same
external-link behavior when it creates the Request.

Example:

```python theme={null}
promote_conversation_to_work(
    title="Backfill the orders mart for July",
)
```

<a id="slack-webhook-tools" />

## `slack_webhook_tools`

Send outbound Slack notifications and Block Kit payloads through incoming webhooks.
Genesis injects `bot_id` and `thread_id` implicitly at runtime, alongside `user_id`;
callers normally provide only the notification fields.

<a id="teams-bot-tools" />

## `teams_bot_tools`

Send proactive messages and list reachable conversations through the Genesis
Teams Bot Framework app. Messages post as the Genesis bot principal, not as a
connected human user or a Power Automate Workflow. Requires the bot to have
Bot Framework credentials configured on **Agents → \[bot] → Teams**, the server-wide
`teams.enabled` switch on, and a stored conversation reference from a prior
install or user message.

Use [Activate Eve in Teams (Bot Framework)](/docs/Workspaces/Microsoft-Teams/Activate-Bot-Framework-Eve-in-Teams)
for Azure Bot, messaging endpoint, and Teams app package setup. For posting via
a workflow webhook URL without a bot install, use `teams_webhook_tools`. For
posting as the connected human user via Graph OAuth, use `teams_tools`.

### `teams_bot_action`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `SEND_PROACTIVE` or `LIST_REACHABLE`. |
| `tenant_id` | string | `null` | Microsoft Entra tenant ID. Required for `SEND_PROACTIVE`. |
| `conversation_id` | string | `null` | Bot Framework conversation ID (for example `a:abcd...`). Required for `SEND_PROACTIVE`. |
| `text` | string | `null` | Plain-text message body for `SEND_PROACTIVE`. |

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at
  runtime, so you normally only provide the business parameters above.
</Tip>

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `SEND_PROACTIVE` | Post `text` to `conversation_id` in `tenant_id`. Requires a stored conversation reference from a prior install or inbound message. | `tenant_id`, `conversation_id`, `text` |
| `LIST_REACHABLE` | List conversations this bot can reach proactively. | none |

Returns a dict with `success` (bool) and either `message` on success or
`error` on failure. `LIST_REACHABLE` adds `conversations` — a list of dicts
with `bot_id`, `tenant_id`, `conversation_id`, `conversation_type`,
`user_name`, `last_seen_at`, and `expires_at`.

Example:

```python theme={null}
teams_bot_action(action="LIST_REACHABLE")

teams_bot_action(
    action="SEND_PROACTIVE",
    tenant_id="YOUR_TENANT_ID",
    conversation_id="a:1abc...",
    text="The long-running export finished.",
)
```

If `SEND_PROACTIVE` returns `success: False` with a message about no stored
conversation reference, the bot has not been seen in that conversation yet —
ask the user to message the bot or install the Genesis Teams app in the target
channel, then retry.

If `SEND_PROACTIVE` returns `success: False` with
`Teams is disabled server-wide (config teams.enabled is false); proactive sends
are refused.`, the operator has turned off the global Teams kill-switch — set
`teams.enabled` back to `true` (or `GENESIS__TEAMS__ENABLED=true`) before
retrying proactive sends.

<a id="teams-tools" />

## `teams_tools`

Send Microsoft Teams channel and chat messages through Microsoft Graph, list
Teams, channels, or chats, and look up users by email. Use
[Microsoft Teams](/docs/Setup/Microsoft-Teams) for Azure App Registration,
OAuth provider bootstrap, and connection setup.

Messages sent by `teams_tools` appear as the connected Microsoft user, not as a
bot. Teams channel messages cannot be deleted through the API, so verify
`team_id` and `channel_id` carefully before sending. Use delegated
**User OAuth** for messaging, listing, and lookup actions. `Client Credentials`
can validate credentials but cannot send, list, or look up in v1.

### `teams`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `SETUP_GUIDE`, `SET_CREDENTIALS`, `TEST_CONNECTION`, `GET_CREDENTIALS_STATUS`, `LIST_TEAMS`, `LIST_CHANNELS`, `LIST_CHATS`, `SEND_CHANNEL_MESSAGE`, `SEND_CHAT_MESSAGE`, or `LOOKUP_USER`. |
| `connection_name` | string | `null` | Optional Microsoft Teams connection name. When omitted, Genesis uses the effective default `microsoft_teams` connection for the current user (**My default**, then **Role default**). |
| `team_id` | string | `null` | Team ID for `LIST_CHANNELS` or `SEND_CHANNEL_MESSAGE`. When omitted on `SEND_CHANNEL_MESSAGE`, Genesis uses the connection `default_team_id` if configured. |
| `channel_id` | string | `null` | Channel ID for `SEND_CHANNEL_MESSAGE`. When omitted, Genesis uses the connection `default_channel_id` if configured. |
| `recipient_email` | string | `null` | Recipient email address for `SEND_CHAT_MESSAGE`. Genesis creates or reuses the 1:1 chat before posting. |
| `email` | string | `null` | Email address for `LOOKUP_USER`. |
| `body` | `object or string` | `null` | Message body for send actions. Use plain text, HTML, or an Adaptive Card body depending on `content_type`. |
| `content_type` | string | `text` | One of `text`, `html`, or `adaptive_card`. |
| `attachments` | array of objects | `null` | Optional file attachments for send actions. Each item has a `uri` and optional `filename`; use a saved result's `query-result://<id>` URI to attach its stored rows as CSV. |
| `credentials_json` | object | `null` | Credentials object for `SET_CREDENTIALS` with `client_id`, `client_secret`, `tenant_id`, and optional `default_team_id` / `default_channel_id`. |

<Tip>
  `bot_id`, `thread_id`, and `user_id` are injected implicitly by Genesis at
  runtime, so you normally only provide the business parameters above.
</Tip>

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `SETUP_GUIDE` | Return Azure App Registration and delegated OAuth setup guidance. | none |
| `SET_CREDENTIALS` | Save app-only credentials for connection testing and future admin use. | `credentials_json` |
| `TEST_CONNECTION` | Validate the current connection. `user_oauth` calls Microsoft Graph `GET /me`; `client_credentials` calls `GET /organization`. | none |
| `GET_CREDENTIALS_STATUS` | Report whether a Teams connection is configured and whether delegated OAuth has completed. | none |
| `LIST_TEAMS` | List Teams joined by the connected Microsoft user. | none |
| `LIST_CHANNELS` | List channels in a Team. | `team_id` |
| `LIST_CHATS` | List chats visible to the connected Microsoft user. | none |
| `SEND_CHANNEL_MESSAGE` | Send a channel message as the connected Microsoft user. When `team_id` or `channel_id` is omitted, Genesis falls back to the connection `default_team_id` or `default_channel_id`. | `body`, plus `team_id` / `channel_id` unless defaults are configured |
| `SEND_CHAT_MESSAGE` | Send a 1:1 chat message as the connected Microsoft user. | `recipient_email`, `body` |
| `LOOKUP_USER` | Look up a Microsoft user by email address. | `email` |

For `content_type="adaptive_card"`, pass the Adaptive Card body itself. Do not
pass the outer Teams wrapper envelope with `type="message"` and
`attachments`; Genesis builds that wrapper for Microsoft Graph.

Example:

```python theme={null}
teams(action="LIST_TEAMS")

teams(
    action="SEND_CHANNEL_MESSAGE",
    team_id="TEAM_ID",
    channel_id="CHANNEL_ID",
    body="Pipeline finished successfully",
    content_type="text"
)

teams(
    action="SEND_CHANNEL_MESSAGE",
    team_id="TEAM_ID",
    channel_id="CHANNEL_ID",
    body="Query totals",
    attachments=[{"uri": "query-result://<query_id>", "filename": "totals.csv"}],
)
```

Adaptive Card example:

```python theme={null}
teams(
    action="SEND_CHANNEL_MESSAGE",
    team_id="TEAM_ID",
    channel_id="CHANNEL_ID",
    content_type="adaptive_card",
    body={
        "type": "AdaptiveCard",
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "version": "1.4",
        "body": [
            {
                "type": "TextBlock",
                "text": "Daily refresh passed",
                "weight": "Bolder",
                "wrap": True
            }
        ]
    }
)
```

Adaptive Card bodies must be JSON objects with `type = "AdaptiveCard"` and a
`body` list. Serialized card size is capped at 28 KB.

<a id="teams-webhook-tools" />

## `teams_webhook_tools`

Send Microsoft Teams alerts, notifications, scheduled reports, approval
handoff cards, raw Adaptive Cards, and recent delivery lookups through
incoming webhook endpoints. This path does not require a
`microsoft_teams` connection or delegated OAuth.

<Tip>
  Typed card actions `SEND_ALERT`, `SEND_SCHEDULED_REPORT`, and
  `SEND_APPROVAL_HANDOFF` render with Genesis branding: a colored header, a
  subtle `Sent by Genesis` footer, and the Genesis logo when it is available
  in the deployment. `SEND_MESSAGE`, `SEND_NOTIFICATION`, and raw
  `SEND_ADAPTIVE_CARD` payloads remain caller-authored pass-through cards.
</Tip>

Genesis accepts HTTPS webhook hosts matching `*.logic.azure.com`,
`*.api.powerplatform.com`, or `*.webhook.office.com`.

<Note>
  Legacy `*.webhook.office.com` Office 365 connector URLs still work but return
  a deprecation warning because Microsoft is retiring that connector family.
  Prefer Microsoft 365 Workflows / Power Automate webhook URLs when possible.
</Note>

### `teams_webhook_action`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `TEST_WEBHOOK`, `SEND_MESSAGE`, `SEND_NOTIFICATION`, `SEND_ADAPTIVE_CARD`, `SEND_ALERT`, `SEND_SCHEDULED_REPORT`, or `SEND_APPROVAL_HANDOFF`. |
| `webhook_url` | string | none | Required. Teams webhook URL or Genesis secret reference containing that URL. |
| `message` | string | `null` | Message body for `SEND_MESSAGE` or `SEND_NOTIFICATION`. |
| `title` | string | `null` | Title for `SEND_NOTIFICATION`, `SEND_ALERT`, `SEND_SCHEDULED_REPORT`, or `SEND_APPROVAL_HANDOFF`. |
| `adaptive_card` | `object or string` | `null` | Raw Adaptive Card body JSON for `SEND_ADAPTIVE_CARD`, not the outer Teams wrapper envelope. |
| `severity` | string | `null` | Alert severity for `SEND_ALERT`: `Critical`, `Warning`, `Info`, or `Good`. |
| `fields` | object | `null` | Optional field map for `SEND_NOTIFICATION` or `SEND_ALERT`. Genesis renders these entries as an Adaptive Card `FactSet`. |
| `sections` | `object[]` | `null` | List of scheduled report sections for `SEND_SCHEDULED_REPORT`. Each section must include `title` plus either `text` or `summary`, or `facts` or `fields`. |
| `action_url` | string | `null` | Optional detail URL for `SEND_ALERT`. Genesis renders it as an `Action.OpenUrl` button titled `Open details`. |
| `generated_at` | string | `null` | Optional generated-at timestamp for `SEND_SCHEDULED_REPORT`. When omitted, Genesis uses the current UTC timestamp. |
| `summary` | string | `null` | Summary text for `SEND_APPROVAL_HANDOFF`. |
| `color` | string | `null` | Optional Adaptive Card title color for `SEND_NOTIFICATION`, such as `Good`, `Warning`, `Attention`, or `Accent`. |

### Available actions

| Action | Description | Required parameters |
| - | - | - |
| `TEST_WEBHOOK` | Send a minimal probe Adaptive Card to validate the webhook. | `webhook_url` |
| `SEND_MESSAGE` | Send a plain-text message wrapped in a minimal Adaptive Card. | `webhook_url`, `message` |
| `SEND_NOTIFICATION` | Send a styled notification with optional title, message, fields, and color. | `webhook_url`, plus `title` and/or `message` |
| `SEND_ADAPTIVE_CARD` | Send a raw Adaptive Card body. Genesis builds the outer Teams webhook envelope. | `webhook_url`, `adaptive_card` |
| `SEND_ALERT` | Send a severity-colored alert card with optional facts and an `Open details` link. | `webhook_url`, `title`, `severity` |
| `SEND_SCHEDULED_REPORT` | Send a report card made of titled sections with section text and/or facts. | `webhook_url`, `title`, `sections` |
| `SEND_APPROVAL_HANDOFF` | Send a display-only approval-handoff card. The card instructs the reader to reply in Genesis to approve or reject; no round-trip button callback is emitted, because the webhook delivery path cannot receive `Action.Submit` events. | `webhook_url`, `title`, `summary` |

<Tip>
  `SEND_ADAPTIVE_CARD` payloads are semantically validated before Genesis sends
  them. Use supported card versions `1.0` through `1.5`, include a non-empty
  `body`, and keep nested elements and actions compatible with the declared
  version. Genesis also checks common required fields such as
  `TextBlock.text`, `TextRun.text`, `Image.url`, and `FactSet` fact
  `title` / `value` pairs.
</Tip>

### Delivery results

Webhook sends retry transient failures up to 3 attempts. Genesis retries
connection errors, timeouts, and HTTP `429`, `500`, `502`, `503`, and `504`.
The result always includes delivery metadata you can inspect or log:

* `delivery_status`: `success`, `retried_success`, or `failed`
* `attempt_count` and `attempts`: retry count plus per-attempt `attempt`,
  `status_code`, `duration_ms`, and `error_excerpt`
* `webhook_host`, `payload_digest_sha256`, and `final_status_code`
* `final_error_excerpt` on failures
* `deprecation_warning_present`, plus `deprecation_warning` when you use a
  legacy `*.webhook.office.com` connector URL

Example:

```python theme={null}
teams_webhook_action(
    action="SEND_NOTIFICATION",
    webhook_url="secret_ops_teams_webhook",
    title="Data Quality Alert",
    message="The reservations_daily freshness check failed.",
    fields={"dataset": "reservations_daily", "status": "failed"},
    color="Attention"
)
```

Alert example:

```python theme={null}
teams_webhook_action(
    action="SEND_ALERT",
    webhook_url="secret_ops_teams_webhook",
    title="Pipeline failed",
    severity="Critical",
    fields={"dag": "daily_load", "status": "failed"},
    action_url="https://example.com/pipelines/daily_load/runs/42"
)
```

Approval handoff example:

```python theme={null}
teams_webhook_action(
    action="SEND_APPROVAL_HANDOFF",
    webhook_url="secret_ops_teams_webhook",
    title="Deploy to production?",
    summary="Promote build 42 after QA sign-off."
)
```

### `teams_webhook_recent_deliveries`

Recall Teams webhook delivery history from the last 7 days across threads.
Use this after `teams_webhook_action` when you need to confirm whether a send
arrived, how many retries it took, or why it failed.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `limit` | integer | `10` | Maximum number of recent delivery rows to return. Genesis clamps this to `1` through `100`. |
| `webhook_host` | string | `null` | Optional exact webhook hostname filter, such as `defaulttenant.region.environment.api.powerplatform.com`. |

Returns a list of delivery summaries with `timestamp_utc`, `bot_id`,
`thread_id`, `tool_action`, `status`, `delivery_status`, `attempt_count`,
`attempts`, `webhook_host`, `payload_digest_sha256`, `final_status_code`,
`final_error_excerpt`, and `deprecation_warning_present`.

Example:

```python theme={null}
teams_webhook_recent_deliveries(
    limit=5,
    webhook_host="defaulttenant.region.environment.api.powerplatform.com"
)
```

<a id="transition-contract-tools" />

## `transition_contract_tools`

Compile and execute **governed transition contracts** with first-hand evidence
for estate migrations (for example Postgres → Databricks). Agents use this
group to characterize source and target inventories, propose table mappings and
correspondence rules, qualify rules against edge fixtures, store transition
objectives, compile contracts, execute verification runs, and render cutover
dossiers.

`characterize_source` only reads estates whose engine can execute the catalog
statements through Genesis's database connector. If the connection names an engine
whose inventory is served through its own transport rather than a SQL catalog surface,
the tool refuses before reading anything with a `NON_DATABASE_ESTATE` error that names
the engine. This is an engine limitation, not a permissions or transient connection
problem; do not retry it or substitute a different database or schema list.
When `schemas` is pinned and `estate_char.characterization.full_source_default` is enabled
(default `true`), the tool performs one schema-discovery read to detect whether the pin
exactly matches the full-source scope. See [Agents and the API](/docs/Genesis-Prover/Agents-And-The-API)
for how that preserves the estate boundary and finding identities.

Estate-backed timestamps returned by this group are UTC-aware ISO-8601 values; see
[Agents and the API](/docs/Genesis-Prover/Agents-And-The-API) for the shared timestamp
contract.

**Human approval is out of band.** Agents can propose correspondence rules and
report whether their fixtures pass, but they cannot qualify or ratify an estate
correspondence rule. A genuinely authenticated human performs those acts for the
concrete estate pair in the **Ratifications** worklist. Transition-contract
artifacts are qualified through Migration verification (`/data/verify/overview/`)
or `POST /api/transition_contract/rules/{rule_hash}/ratify`; when compile or
execute hits the license gate, chat shows an inline `transition_contract_refusal`
card with the refusal case and a deep link to Migration verification.

When an agent proposes an estate rule, its display name from the runtime bot
registry is recorded when available, so a person can identify the proposal as
coming from that agent (for example, “from Eve”). The rule-list response fields
are documented in the [correspondence-rules API reference](/docs/Genesis-API/API-Reference#get-api-estate-correspondence-rules).

Long-running transition verification is handed to the registered serving loop. If
that hand-off is refused, the affected run is closed with `status: "error"` and the
tool returns `success: false` plus its `run_id`, so callers should not keep polling it
as `running`. If closing the row also fails, the response includes
`terminalization_failed: true` and the row may remain `running` until startup
reconciliation.

`characterize_source` accepts `notify` (boolean, default `true`) alongside its
bounded `wait_seconds` window. When it is enabled from a Genesis thread, the thread
receives the terminal result on its next tool result, or in a new turn after it goes
idle, so it does not need to poll `get_characterization_run`. Set `notify=false` when
you specifically want to check the run yourself.

The comparison-scoped worklist filters foreign proposals and exposes `blocked_reason`
for proposals that remain visible but cannot be approved; see the [worklist and
withdrawal endpoint](/docs/Genesis-API/API-Reference#post-api-estate-correspondence-rules-rule-id-withdraw).
Its rows also expose `default_refusal` for rules that must not be offered as
pre-ticked platform defaults; see the [rule-review endpoint](/docs/Genesis-API/API-Reference#get-api-estate-rule-reviews)
for the response semantics.

Withdrawing a correspondence proposal is allowed only while both the rule definition
and this comparison's binding still say `proposed`. If the definition is retired, the
pair binding was revoked, or the rule is ratified for this pair, the refusal explains
that state and says there is nothing to withdraw. If this pair has no binding, the
response reports that fact without treating a definition's historical `ratified` flag
as a live licence for this comparison; revocation is a human authority act, not a
proposal withdrawal.

The proven `bigquery->databricks` pair has default binding correspondence decals,
so its observed type-name spellings and value-rendering differences are licensed
without per-migration ratification. This covers exact-preserving mappings such as
`NUMERIC` to `decimal`, `INT64` to `bigint`, and UTC timestamp or decimal-scale
rendering differences. The built-in `mssql->snowflake` type rule also licenses
T-SQL `float(53)`, `float(24)`, and `real` against Snowflake `FLOAT` (the target's
single 64-bit float representation), including Snowflake's equivalent float
spellings such as `DOUBLE`. Exact decimal and numeric types remain distinct from
this approximate-float family, so a decimal-to-float change is still unlicensed.
The built-in `mssql->databricks` pack also covers T-SQL `varbinary`, `binary`, and
`image` storage families to Spark `binary`, the two-valued `bit` rendering (`1`/`0`
to `true`/`false`), and UTC or offset-less `datetime2`, `smalldatetime`, and
`datetimeoffset` renderings to Spark timestamps. These are checkbox rules: binary
value differences remain content findings, `NULL` remains owned by nullability,
and a non-UTC offset still flags because it can identify a different instant.
It also includes a checkbox rule for T-SQL `geography` and `geometry` (including
`geography(max)` and `geometry(max)`) rendered as Spark `string`. This licenses
the type spelling only: spatial values are not compared, their content and
boundary findings remain indeterminate, and the target text is not asserted to be
well-formed WKT, WKB hex, or GeoJSON. The reverse mapping and `xml`→`string` are
not covered.
For text distinct-count comparisons, the MSSQL digest adapter now hashes the
operand with a SQL Server 2019+ `_UTF8` collation so byte-identical non-ASCII
content can be corroborated against Databricks' UTF-8 digest.
The same `mssql->databricks` pack recognizes engine-issued surrogate keys from
source catalog provenance: SQL Server `IDENTITY` columns, columns whose
`DEFAULT` draws from a `SEQUENCE`, and declared foreign keys onto those columns.
It licenses value-level differences that can result from rebuild renumbering,
including bounds, content digests, and category distributions, but not
cardinality differences. The rule is source-side and does not use a column-name
pattern, so date columns such as `Invoice Date Key` remain ordinary findings.
When the schema has no foreign key for a known engine-issued ledger, a named
person may pass a `provenance_assertions` proposal to `characterize_source` to
identify the source column and its exact dependent columns. The scan verifies
the source against the live catalog and refuses contradictory assertions; the
proposal only makes those columns eligible for the ordinary rule, which still
requires binding and human ratification.
The built-in `sqlite->databricks` and `sqlite->snowflake` packs likewise seed
assumptions for proven exact type spellings, so those spellings are not reported as
findings by default. The precise mappings and the rejected narrowing or cross-class
landings are documented in [Genesis Prover's assumption rules](/docs/Genesis-Prover/Overview#fresh-licensing-evidence).
The `postgres->snowflake` and `postgres->databricks` pairs also have built-in platform
type rules. They bind automatically as declared-type assumptions rather than pack
proposals; `built_in_count` includes these rules when `availability_only=true`. Their
exact type-preserving mappings and limits are described in [Genesis Prover's assumption
rules](/docs/Genesis-Prover/Overview#fresh-licensing-evidence).
Genuine value changes, lossy cross-class mappings, and unmapped types remain
unlicensed and are still reported by the diff.

For the structural-only eligibility boundary and single-rule path for
data-derived differences, see the [platform-default consent endpoint](/docs/Genesis-API/API-Reference#post-api-estate-correspondence-rules-accept-defaults).

**Row-identity keys** can be single-column or composite. Compiled obligation
frames carry `key_columns` (ordered list) and `key_source` (`declared` when the
source estate supplied the key, `designated` when a human asserted it). The legacy
`key_column` field is populated only for single-column keys. A human **key
designation** — asserting which columns identify rows when neither estate declared
one — is also out of band: `put_transition_objective` refuses objectives that
include `key_designations`. Operators designate keys from the run-detail UI or
via `POST /api/transition_contract/objectives/{objective_hash}/designate-keys`,
which derives an immutable successor objective. Column order in a designation is
significant — it becomes the comparison sort order.

For keyed table spot checks without the transition-contract registry, use
`verify_against_contract` from `system_diff_tools` instead.

| Tool | Purpose |
| - | - |
| `characterize_source` | Create first-hand inventory evidence for a database endpoint (`connection_id`, `database`, `schemas`, optional `watermark_note`, and `provenance_assertions` for named engine-issued-key relationships missing from the schema). |
| `propose_addressing_map` | Propose object rename mappings between characterized estates. |
| `propose_transition_contract_rule` | Author a correspondence rule artifact for a measurement class and component pair. |
| `qualify_transition_contract_rule` | Record qualification test evidence (fixture verdicts) for a rule. |
| `ratify_correspondence_rule` | Return the Ratifications worklist link; a human qualifies and ratifies the estate rule there. |
| `ratify_delta` | Return the System diff panel link; a human ratifies the declared delta there. |
| `put_transition_objective` | Store a transition objective that lists the mappings and rules for one migration. |
| `compile_transition_contract` | Compile a stored objective into a governed contract (`objective_hash`). |
| `execute_transition_contract` | Submit a compiled contract for verification (`contract_hash`). |
| `get_transition_run` | Poll one verification run by `run_id`. |
| `get_transition_dossier` | Render the human-review cutover dossier for a compiled contract (`contract_hash`). |

### `ratify_correspondence_rule`

This tool does not ratify a rule. It refuses the agent's authority act and returns
the Ratifications worklist address for the human operator to qualify and ratify
the rule in the specific estate comparison. Pass `diff_hash` when available so
the worklist opens on that comparison; without it, the returned `actionable` value
is `false` and the Qualify and Ratify controls are disabled.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `rule_id` | string | none | Accepted for compatibility, but the agent does not use it to ratify the rule. |
| `diff_hash` | string | none | Optional hash of the stored system diff to pin in the Ratifications worklist. |

Returns `success: false`, an authority-refusal `error`, `ratification_url`, and
`actionable`. The refusal identifies that ratification is a named human's act.

### `ratify_delta`

This tool does not ratify a declared delta. It returns an authority refusal and
the System diff panel address, where the human operator performs the delta Ratify
action. It returns `actionable: true` because that panel owns the control and does
not require a comparison-specific deep-link parameter.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `delta_hash` | string | none | Accepted for compatibility, but the agent does not use it to ratify the delta. |

Returns `success: false`, an authority-refusal `error`, `ratification_url`, and
`actionable`.

See [Data Explorer — Migration verification](/docs/User-Guide/Data-Explorer#migration-verification) for the operator UI and [transition-contract API](/docs/Genesis-API/API-Reference#transition-contract-endpoints) for REST equivalents.

<a id="spec-author-tools" />

## `spec_author_tools`

Author a sealed conformance spec incrementally in one thread. Assign this
persistent group to an agent that needs to write structural checks and
derivational obligations against a live, read-only estate without inspecting
the build target. Register each item separately, resolve estate-grounded
ambiguities, then seal the validated artifact to a content-addressed
`spec_hash`.

See [`_query_database`](/docs/Genbot-Toolkit/Data-Connector-Tools#_query_database).

Source-side `source_sql` and source-relation invariants are resolution-checked when
registered, each in the form its dialect resolves without running the statement:
`EXPLAIN` where the dialect has that verb, a prepare-only call on SQL Server, and a
zero-row derived-table probe on every other engine, including Palantir Foundry. Foundry
connections are transport-backed rather than `DatabaseConnector` connections, so the
authoring gate reaches the tenant through the saved `palantir_foundry` connection and
uses Spark SQL identifier quoting (backticks). A refusal names the resolution form that
was actually sent, so a Foundry failure is not reported as an unsupported `EXPLAIN` check.
A recompute's `grain_probe` runs against the estate at registration time; undeclared
fan-out is rejected with the measured row and key counts, while `fanout_declared` accepts
the author's rationale and returns the measurements. Target-side SQL and target-relation
invariants are not executed during authoring because the build target may not exist yet.
When the run places the target on an engine with a supported SQLGlot dialect,
`register_obligation` parses each non-empty `target_sql` in that dialect and refuses syntax
or dialect errors with the parser's message. This checks syntax only: it does not resolve
columns or functions or check types, which remain for the target engine at sealing. The
parse is skipped when the run places no target or the engine has no supported dialect.
When a blind compile has a target snapshot, the server uses its characterized column types
only to decide whether a synthesized numeric domain invariant can resolve. It synthesizes
numeric bounds only for characterized numeric target columns; projection aliases
and non-numeric columns with numeric-looking names are recorded as
`unresolvable_domain_invariant` notes instead of being emitted as checks against
the base relation. The target characterization remains server-side and is never
included in the author's brief.

The blind compile scopes a large source catalog before building its authoring
brief. Relations named by the instruction are shown first, followed by
name-adjacent relations, schema siblings, and then the remaining catalog
entries, subject to the render bound.
Existence checks still use the complete bound catalog, not only the relations
shown in the brief. Consequently, declare an already-held relation with the
change kind for an existing relation rather than `add_table` or
`add_derived_mart`, and do not declare an already-held column with
`add_column`. Source-side SQL in obligations must read relations held by the
source catalog (or relations declared as build outputs); a same-named relation
found only in the target catalog does not count as source-held. Unresolved catalog
references and structural/catalog kind conflicts are retried within the
bounded authoring loop. If the retry cannot resolve one, the seal is refused
and the finding is returned in `validation_findings`.

At `finalize_spec`, an `add_table` item is refused with rule
`add_table_source_held` when the latest source scan resolves its locus by name and
either the object is file-backed or a complete target scan has no object in the
source object's schema. It is also refused when the latest target scan's table at the
locus has files matching exactly one file-backed source object. This covers
file-backed datasets even though their SQL read reports no schema. The refusal names
the held object and any `add_column` items on the same locus; carry the object in
scope instead (`same` if unchanged, `changed` if the ticket orders a change), and
remove those structural items. If they came from a prior spec, declare the deletion
with an `amendments_json` entry before finalizing. See [Foundry datasets without a
schema](/docs/Genesis-Prover/Overview#foundry-datasets-without-a-schema) for how the
Prover measures those files.

### Relation observation evidence

The seal requires evidence that each relation named on an obligation's **source**
side was observed during authoring; it does not require one particular bind
mechanism. A receipt records the normalized `relation`, `observed_via`,
`transport`, `connection`, `observed_at`, and `receipt_basis`. The `connection`
is the estate the read was taken through, not merely the connection bound to the
thread. The available `observed_via`
values are `bind_probe` (the zero-row resolution check), `transport_query` (the
same check through a registered query transport), `catalog_read` (the estate
catalog returned that relation's columns), and `sample_read` (an executed query
returned rows). The receipts are written to `seal.json` beside the compiled
artifact, so they document how the estate was observed without changing the
artifact's `spec_hash`.

`finalize_spec` also records observation receipts when its source-engine
preparation accepts a deferred source-side statement; those receipts enter the
evidence ledger on the next round.

Relations declared as outputs by this spec are deferred until post-build
grading. In a repair round, source relations already named by the prior sealed
spec are carried with the prior `spec_hash`; a newly introduced source relation
still needs a receipt.

A declared output is not taken on the declaration alone. The gate resolves every
registered relation against the **measured catalog of the bound estate** — the estate's
own enumeration of the schemas the payload names — never against the text that registered
it. A relation declared created by a structural item or by the scope's `new` entry is
deferred until grading and must be absent from that catalog: a `new` object the estate
already holds is not new. A structural item and scope may both declare the same relation;
the structural item is the receipt's named declarer. A create that neither declares is a
fabrication, and both kinds of conflict refuse by name. A thread that has registered **no scope at all** is the partial
exception — a repair round seeded from a prior seal carries structural items and no scope —
and there only the SCOPE question is skipped: the create is reported unmeasured instead of
refused for being unscoped. The catalog question is still asked, because "the estate
already holds this" is an independent conflict that the scope has no bearing on, so a
scopeless create whose relation the measured catalog holds is still refused by name.

The check is per **relation**, not per statement: a statement that reads a declared output
alongside other relations still has those other names checked against the catalog. Those
are the refusals that offer **nearest measured names** — a name read beside a deferred one
is a candidate misspelling, so the catalog's closest spellings help. A create refusal does
not offer them: the remedy there is to scope the object or drop the create-declaration,
not to correct a spelling.

An accepted `register_obligation` response carries `resolution_clean`, which is a
**measurement, not an assertion**. It is `true` only when every relation the call touched
was seen — planned against the estate, or confirmed `new` by the scope and absent from the
catalog. It is `false` when something was not measured, and the response then names what:
`resolution_unprobed` for statements nothing was sent for (a connection type this process
cannot execute against), and `resolution_unmeasured` for relations the catalog would not
answer about. `resolution_deferred` lists the statements held back because they read a
relation this spec creates. On a run that places source and target in separate catalogs of
one connection, a declared `invariant_side: "target"` is bind-checked only in the target
catalog; successful checks appear in `resolution_target_catalog` and do not create source
observation receipts. Target-side query evaluation remains deferred to grading.

Before writing the sealed artifact, `finalize_spec` refuses any finding from
the artifact's seal gate: invalid artifact shape, a commitment rule activated
by the artifact's doctrine stamp, or a catalog conflict that the bounded retry
could not resolve. Every multi-member `ambiguity_group` must carry a committed
`lean` on one of its members, or a written `abstention` explaining why the axis
cannot be leaned. Assertions must also stay at the resolution stated by their
own rationale: for example, a rationale that records an exact measurement must
not be sealed as a presence-only check or with a looser tolerance. The
`validation_findings` in the compile result report the same findings that
caused the seal decision.

### Spec-author identity and constitution

Genesis seeds the built-in `spec-author` system agent as a normal bot that can
open a thread. Its default thread-start loadout includes `context_tools`,
`spec_author_tools`, and `data_connector_tools`; these are defaults rather than
a confinement, because the bot uses `tool_access_mode: "all"`. The agent's
authoring boundary is enforced inside each tool, not by the advertised tool
list.

The seal provenance records `surface: "seat"` only when the spec-author identity is the
only contributor to the draft. A direct call to these tools from another agent records
`surface: "tool"`, even if that caller later invokes `finalize_spec`; direct tool calls
are outside the seat's constitution. Use `author_spec` when the ticket must be authored
under the seat's constitution.

The agent's identity names the `spec-author-constitution` skill and the pinned
constitution, which ships as three files — `constitution_v9_34.md`,
`constitution_v9_34_part2.md` and `constitution_v9_34_part3.md` (version `v9_34`,
`sha256:7f0d4d4fe9641de07d05c53f901112486de7ea9288af7323148fb6489a3f6bb6` over the three
concatenated in that order). It is split because the assigned-skill reader serves at most
50,000 characters per file; the three are one document and the pin covers all of them. Read
every file in full before the first estate query or registration call; the reads may run in
parallel. If any reply reports `truncated: true`, follow that file's `continuation_hint`
until it reports `truncated: false`. Every sealed spec records the constitution version and
hash used to author it.

The `open` interpretation policy and its `spec-author-open` bot are retired: `lean` is the
only policy, and `author_spec` refuses a run that names `open`.

Constitution v9.5 makes collection normalization explicit: when a check reduces a
collection to one value, its source and target expressions must define what an empty
collection and a `NULL` collection become, rather than relying on dialect defaults. If the
ticket is silent, normalize both sides to one representation (commonly
`NULLIF(<joined>, '')`) and state that choice in the rationale; apply the same rule to
`NULL` elements inside a collection. A target statement the engine accepts is also run
over at most 1,000 rows of each relation it reads, which catches an error a real row raises
(an array index past the end) only when such a row is in the sample, and says nothing about
which value an empty collection becomes, so it does not settle this empty-versus-`NULL`
behavior.

Constitution v9.6 treats a declared unknown member as a row of its target: when the mapping
declares an unknown member, a ghost or a placeholder row (a dimension's `-1` surrogate, a
hub's ghost key), every domain rule over that relation must exclude it — written as a
`recompute` whose `target_sql` filters the member out by its key — and the member is
asserted in its own check. An `invariant` has no row filter, so it is evaluated over the
member too.

Constitution v9.10 also requires checks for period-derived flags such as an effectivity
satellite's `is_active` to be evaluated against the rows the clause itself produces. Before
registering the check, work through one ended and one still-open relationship with each row's
flag, and verify the predicate counts zero contradictions; a target-side sample cannot establish
that the check matches the clause. The v9.10 seal refusals are listed under
[`finalize_spec`](#finalize_spec). Constitution v9.22 tells the seat that a commissioned run
which places no target is refused at the seal under `target_not_placed`, which only the
commissioning caller can fix, and that a check the degeneracy probe measures degenerate no
longer decides an item on a carried column. Constitution v9.23 restates that doctrine as one
current text, with every amendment folded into the section it governs; no rule changed.
Constitution v9.24 states that a lift-and-shift (a scope with no `changed` and no `new`
entry) always carries one explicit `membership` obligation, and the seal refuses one without it.
Constitution v9.28 retains floor F1-D for derived builds: when scope contains an `input` or the
registered mapping declares a derived target, structural items must describe ordered outputs
on the target side, including required column items. The seal also checks that each output's
linked obligations are explicit and that outputs are scoped `new`, except an image carried
under its legacy object's name, which is `changed`; see [`finalize_spec`](#finalize_spec)
for the refusal conditions and [the Registrar guide](#spec-author-registrar-tools) for the
registration workflow. Constitution v9.27 scopes a carried image that keeps its legacy
object's name `changed` and a renamed image `new` (the source already holds a same-name
image, so `new` would declare it created and refuse every check reading the legacy object),
and the derived-build seal also refuses a column item the grade attributes no check to.
Constitution v9.28 states how a conditional rule is encoded: "when X, then Y" is a
`self_consistency` violation count over the target — `source_sql` `SELECT 1 AS grp, 0 AS
violations`, a `target_sql` counting the rows where X holds and Y does not, keyed on `grp` —
expected 0, never a `membership` between an X-filtered side and an unfiltered or Y-filtered
side. A membership restricted to the same population on both sides stays a membership, and
de-duplication or current-row filters are not conditions. This is the check the
`conditional_rule_advisory` from `register_obligation` already names.

Constitution v9.29 adds partial seals. A numbered clause the seat cannot prove yet is
accounted for as `open` with `register_clause_accounting`; its accepted reasons, remedy
fields, and reserved mapping values are listed in the tool reference below. The rest of the
spec seals. The open clauses are sealed in the artifact's
`coverage` block, inside its hash, and the seat run reads `sealed_partial`. The seal refuses
an open clause with no reason, remedy and evidence (`open_without_remedy`), and a ledger that
seals no clause at all (`nothing_sealable`), which still declines. The seat examines every
mapping entry and clause before it returns, and a finding against the mapping still declines
the run: the `mapping_entry_contested` reason and the `supply_mapping` / `restate_entry`
remedy kinds are reserved, and refused (`reserved_open_value`). A follow-up is commissioned with `repair_of` naming the partial seal:
`load_prior_spec` returns open clauses still stated in the repair document as
`open_clause_drafts`; clauses moved to another key or absent from that document are reported
separately. The reseal re-runs every gate.

Constitution v9.30 lets the seat decide what a migration already answers. A run stops when
it does not understand the DATA. It never stops merely because a decision hasn't been
rubber-stamped. Where the target reproduces the source — an object scoped `same`, or an
output that must match a reference — the preserve-the-source properties (NULL counts, empty
string vs NULL, whole-row multisets on every table in scope, type families, nullability, row
identity, the row count per key, value domains, referential integrity) are migration
defaults: the seat adopts them silently and never asks the owner (v9.31: if the answer would be
the same for every customer, it is not a question). On a `same` object the system diff checks them from both estates'
characterization, and the seal refuses a check that restates one. On a derived output the seat
registers the check with `requirement_source` `{"kind": "migration_default", "property",
"citation": "migration default: target reproduces source — …"}`, and a default that reads no
target is refused. A question about what the source holds is answered by measurement, never
asked: the seat reuses existing measurements and, when profiling is needed, runs one profile
query per table rather than one query per question, profiling at most 200 columns. Only an
intended deviation (a rename or drop with no stated reason, a business rule nothing measures)
goes to the owner, as an `open` clause whose owner remedy carries a `recommended_answer` (so does
an operator remedy: a person is never handed a bare question, and since v9.31 is asked in the
business terms of their own data, with no Prover vocabulary); the
rest of the spec seals. A clause is `not_applicable` only with
`evidence` measured on the source or the `ruling_id` of a clarification the run was
commissioned with; a ticket calling a clause "out of scope" is not a ruling, and a clause the
seat cannot prove is `open`.

The Prover Spec Registrar is the first product seat declared by Genesis. Its durable principal is
`agent:spec-author`, and its escalation mode is configured per deployment rather than per
thread. The default `human` mode reports an estate question the seat cannot settle and may
hold the compile; set `estate_char.spec_author.escalation_mode` to `"autonomous"` for a
deployment with no human court, so the seat forks the reading, annotates the artifact, and
continues. The setting is read at call time and unrecognized values fail closed to `"human"`.
See [In-product spec author settings](/docs/Setup/Advanced-Settings#in-product-spec-author-estate_char.spec_author)
for the complete configuration entry.

When a spec-author run is submitted through the API, the returned run uses the same
envelope as every other Prover run. By default it is asynchronous; callers may provide
`wait_seconds` when they prefer a bounded wait, with the ceiling and expiry reported in
the response. See the [author-seat API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-author-seat)
for the request parameter and response behavior.

Every tool in this group — every row of the table below, with no exceptions — refuses the
call when the constitution skill is not active, cannot be read, or resolves to
bytes that do not match the pinned hash. Activate the skill with
`manage_context(action="ADD_CONTEXT", active_skills="spec-author-constitution")`,
then read the constitution before retrying.

`finalize_spec` also verifies the constitution that this thread actually received. The
thread must have been served exactly the two pinned files, in the pinned order, with
contiguous pages from each file; Genesis compares each file's recorded SHA-256 with the
pin before sealing. Missing or extra files, out-of-order reads, interrupted paging, or a
per-file digest mismatch refuse the seal. Read both pinned files again from the first file
in the required order, then retry `finalize_spec`. A successful seal records the aggregate
constitution pin (`constitution`: name, version, SHA-256) as its doctrine identity; the
per-file check happens before the seal and is not repeated on it.

The pinned constitution also teaches three seal-gate requirements that affect every
registered check. Quote relation and column identifiers using the case stored in the
bound estate, including identifiers in `source_sql`, `target_sql`, `grain_probe`,
`invariants[].column`, and `envelope_receipt.derivation_sql`. Genesis preserves plain
identifiers so the warehouse can apply its normal case folding, and automatically uses
the registered connection's dialect quoting for names that need it, such as
`Fact.Stock Holding` or a column named `Stock Item Key`; the gate reports
`r6_quoted_identifier_unresolved` or `r6_catalog_unmeasured` when that evidence is
missing or does not match. Keep the source side blind to the build: `source_sql` and
source-side invariants must not read a relation the spec asks the builder to create or
a column it asks the builder to add, or the gate reports
`r7_source_reads_created_relation` or `r7_source_reads_added_column`. Finally, when
an author chooses a value-obligation tolerance, it must cover the measured
quantisation envelope and include a re-runnable `envelope_receipt`; the gate refuses
an under-sized or non-executable receipt with `p6_envelope_receipt_failed`. Tolerances
that come directly from the ticket are not changed by this requirement. R7 binds only
the source side: `target_sql` and target-side invariants read the target as the subject
of a check, and `finalize_spec` prepares and samples them on the target.

When a structural item declares `expected_type`, `expected_type_family`, or
`expected_scale`, include `type_license` as `"ticket"` or `"inferred"`; see the
[compile API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-compile)
for how the tag affects type-mismatch severity.

`expected_type_family` accepts `numeric`, `text`, `date`, `timestamp`, `temporal`,
`boolean`, or `binary`. `expected_scale` is a non-negative integer for numeric
declarations; omit both fields when the structural item should use existence-only
grading.

Structural loci must use the addressing contract expected by the Prover: whole-object
changes use `schema.table`, while column-level changes use `schema.table.column`. Do not
include a catalog or database prefix, leave any component blank, or put a column component
on `add_table`, `add_derived_mart`, `drop_table`, or `drop_constraint`. When a blind author
compile has a target snapshot, the schema component is also checked against the target's
namespaces case-insensitively; a locus that still violates the contract after the bounded
retry remains in the run's validation findings rather than being silently discarded.

During grading, a sealed deliverable may use the graded side's catalog-qualified spelling
(`target_catalog.schema.table` or `target_catalog.schema.table.column`). When
`target_catalog` is supplied to the grading endpoint and matches that leading catalog,
the Prover strips it for attribution and emits the canonical `schema.table[.column]` locus.
Catalog-qualified targets for any other catalog remain unmatched; use the catalog that the
graded side actually resolves against.

Compiled-spec verification records the catalogs that each obligation actually read as
`source_catalog_effective` and `target_catalog_effective`. A keyed obligation records both
bound catalogs; an invariant records only the side it graded and leaves the other field
`null`. An `ERROR` obligation leaves both fields `null` because no verdict was read. When
source and target use the same connection, selecting `invariant_side="target"` also
requires `target_catalog`; without it, the verifier refuses the invariant rather than
silently grading the source catalog.

Invariant verification also reports `rows_compared`, the population examined by the same
scan as the violation count; see the [compiled spec API response](/docs/Genesis-API/API-Reference#post-api-estate-verifications) for the response contract and its `null` error behavior.

Relations are named `schema.relation`; the database or catalog is a property of the
bound connection, not of the item. Three segments are ambiguous, because the per-column
locus `schema.relation.column` has the same depth as `catalog.schema.relation`, so a
three-part name is RESOLVED against the bound catalog rather than assumed:

* leading part IS the connection's database — normalized to two parts, in the locus and in
  every SQL field, outside string literals and comments; the reply names what it rewrote;
* leading part is a schema of the bound catalog — a column locus, preserved exactly;
* anything else, or a catalog that cannot be read — preserved and UNCHECKED, never refused,
  because the two shapes cannot be told apart without that fact.

A foreign database is refused only for a SQL `FROM`/`JOIN` target, where three segments are
unambiguous: a read position cannot be `schema.relation.column`. A build that lands in a
different database can never hold such a name.

Normalization is re-applied at `finalize_spec` to everything the draft holds, so the rule
does not depend on the order items were registered in or on a connection lookup that failed
earlier.

For `register_obligation` and `register_settlement`, an omitted `connection_id`
uses the connection already bound by an earlier registration in the same thread;
an explicit connection always wins. There is no default estate: a thread that has
bound no connection refuses the call with `no connection bound for this thread`
rather than choosing one, so the first registration of a run must name it. The
estate checks and grounding query
run as the requesting caller, so that caller must have access to the selected
connection's credential. `register_structural` does not bind or change a
thread's connection. When an estate check cannot reach the selected connection
or resolve its credential for the caller, the tool reports an access problem
rather than treating the SQL as an unresolved relation; re-register with the
connection used by the rest of the run, or ask the stack administrator to grant
the caller access to the connection's secret, instead of renaming relations or
columns.

Catalog checks use the selected connection's platform-specific metadata capability,
not a universal `information_schema` query. If the caller can reach the estate but
cannot read its catalog under the bound role, `register_obligation` keeps the
obligation and records `unmeasurable_under_role` with the role or login that could
not enumerate it; it does not narrow the obligation to the objects that happened to
be visible. A catalog read that reaches its row cap is also treated as unknown rather
than as a partial catalog.

The group is prototype-scoped: in-progress drafts are held in memory per
thread and are lost on process restart. Successful `finalize_spec` calls write
`compiled_spec.json` and `seal.json` under
`~/proto_agentic/<thread_id>/`, then register the sealed artifact with the
source-contract front door. A front-door failure does not remove the disk
seal; the tool reports `REGISTRATION_FAILED` so it can be registered manually
through the [compiled spec API](/docs/Genesis-API/API-Reference#estate-endpoints).
Finalized artifacts can be used as relocation-proof evidence; see [Relocation proofs
bind once](/docs/Genesis-Prover/How-A-Run-Works#relocation-proofs-bind-once).

For a repair round, call `load_prior_spec` once before any other registration
tool. It seeds the empty draft with the prior artifact's structural items and
obligations, preserving their SQL bodies, tolerances, and probes. Settlements
are not seeded because the sealed artifact stores them in `notes`; the response
returns those notes verbatim and parses their `SETTLEMENTS` entries into drafts
ready for `register_settlement`. Re-registering
an item replaces that entry, while untouched items remain in the new seal. The
tool refuses to seed a draft that already contains registered work. The clause ledger is
the exception to whole-artifact seeding: it is matched to the document this round was handed,
by clause wording before key, so renumbered clauses follow their wording and entries for
clauses no longer stated are returned separately.

A repair round needs no file access to the prior artifact. `load_prior_spec`
returns a manifest of every seeded `spec_id` and `obligation_id` with the
relations it names and the named fork axis it belongs to; `list_draft` returns
that manifest again at any point in the round; and `add_lean` commits a fork by
attaching a `lean` to one member addressed by id, without resubmitting the
member's SQL, tolerance, keys, or rationale.

A seeded repair round is a diff against the prior artifact, not a re-authoring. Every
obligation and structural item must carry forward byte-identically except for edits made by
the finalize-time relation normalizer or an explicit amendment. The default `round_kind` is
`qualify`: it may give relation names their schema, but refuses a weakening even when an
amendment supplies a basis. Use `round_kind="authoring"` only when the spec is deliberately
being re-authored against new information; a weakening or deletion then still requires a
named amendment with a non-empty basis. Deleting an obligation or structural item is named
with `field="<deleted>"`. Unlicensed changes are refused rather than silently resealed.

An amendment can change one field of a carried obligation without re-registering its full
body: give `finalize_spec` an `amendments_json` entry with its `obligation_id`, `field`,
`to`, and a non-empty `basis`. The seal keeps the same id and every other sealed field;
declare the amendment on each finalize call that should apply it. For example,
`[{"obligation_id":"obl-1","field":"title","to":"Current customer key","basis":"The owner clarified the check title"}]` changes only the title. A reworded title or rationale does not require
`round_kind="authoring"` because it does not weaken the carried check.

On a Registrar repair round, an owner clarification can also authorize withdrawing one
carried obligation through `withdraw_obligation` with its clarification id as `ruling_id`.
That ruling is recorded with the withdrawal and licenses the deletion in the reseal;
other carried obligations remain in place. See [`withdraw_obligation`](#withdraw_obligation)
for the parameter and restrictions.

Classic repair tooling has no `withdraw_obligation` verb. Declare the ruled deletion on
`finalize_spec` instead, using the carried obligation's id and the commissioned
clarification's id: `[{"obligation_id":"obl-1","field":"<deleted>","ruling_id":"clarification-1","basis":"The owner ruled this check out"}]`.
The seal removes only that check under the named ruling, whatever the round kind, and
records it in the finalize round's `ruled_withdrawals`. The ruling must be one of the
clarifications this run was commissioned with; an uncommissioned id refuses the round
without sealing or removing anything. For other deletion amendments, the seeded-round
diff rules still apply.

When a repair round re-registers a seeded structural item or obligation unchanged, the
registration carries the prior declaration's conditional fields and is accepted even if a
current conditional rule would reject that already-sealed shape. This applies to the
structural type-declaration fields (`expected_type`, `expected_type_family`, and
`expected_scale`) and to the obligation's conditional declaration fields (`kind`, `root_axis`,
`elected_reading`, `eliminated_reading`, `elimination_evidence`, `ambiguity_group`,
`target_sql`, and `measured_by`); adding, removing, or changing any of those fields makes the
item newly authored and runs the conditional validation again. A new item, or an item whose
identity was not present in the seeded seal, is always validated as new.

| Tool | Purpose |
| - | - |
| `load_prior_spec` | Seed an empty repair draft from a prior sealed `compiled_spec.json`; structural items and obligations are preserved. Returns the prior `notes` verbatim, its `SETTLEMENTS` entries as `register_settlement` drafts, and a manifest of the seeded ids. The clause ledger is narrowed to the current document: wording matches first, then keys, and only entries for clauses it states are carried. For a partial seal, `open_clause_drafts` contains only open clauses carried into this round, in the shape accepted by `register_clause_accounting`. Entries not carried, moved to a new key, or carried with words that differ from the document are reported in the corresponding `clause_accounting_not_carried`, `clause_accounting_rekeyed`, or `clause_accounting_reworded` fields in the response. A handed document also causes prior `NOT APPLICABLE` entries without a measurement of a name in the clause or an owner ruling still in force to be withheld and reported for re-accounting. If this round has no readable document, the prior ledger is carried as usual. |
| `read_spec_asset` | Read, 50,000 characters at a time, a document the caller handed the seat as an asset (inline `content` or a `repository` file, stored with the run and not in the brief). Pass the exact asset `name` from the intake inventory and optional `start_char` (default `0`); each reply returns `content`, `start_char`, `chars`, `content_sha256`, `truncated`, and `next_start_char` for the next page. Its numbered items and table rows are clauses the seal counts, keyed `<asset>#<key>`. Cost: one run-row read and one read of the stored document; no estate query. |
| `list_draft` | List the in-progress draft's `spec_id`s and `obligation_id`s with their relations, fork membership, and lean state. Reads memory only; runs no query. |
| `register_scope` | Register the objects this spec governs and what it expects of each (floor F0) — one entry per object, with `expectation` one of `same` (arrives unchanged; the DEFAULT, and it costs no structural item and no obligation), `changed` (must arrive DIFFERENT), `new` (must be on the target), `excluded` (must NOT be), or `input` (SOURCE material the change reads and does not carry across: met when the target holds nothing under its name and either the run's mapping loads it into no image (a no-image split, a derived target's source, or a relation declared in an image's `history`) or the target is another estate or does not hold its schema; when the target's copy is unchanged from the source; or when only the target holds it and the source is another estate or does not hold its schema; a changed copy stays open for review, because the mapping and the target disagree; otherwise present on the target is reported and attributed to nobody, and absent is not a finding). If a registered target model splits an object into images, `same` on that object is refused immediately by `register_scope` under `same_over_split` (including when an image keeps the object's name); register each image instead, citing its mapping row: an image under a new name as `new`, and an image that keeps the object's name as `changed`. `new` on an image that keeps its legacy object's name is refused under `new_over_carried_image`, since the source already holds it. Keyed on `object`, so re-registering one REPLACES it; entries accumulate across calls. Rejects the whole batch when any entry is malformed or violates this rule. |
| `withdraw_scope` | Withdraw scope entries this thread registered. See [parameters and behavior](#withdraw_scope). |
| `register_structural` | Validate and accumulate one structural `ChangeKind` item. Re-registering the same `spec_id` replaces the prior item. Derived-build items may include `inputs` (a list of source-coordinate `{locus, role}` objects or locus strings; `role` is `value`, `key`, `filter`, `join`, or `rowset`; `[]` declares a constant, while omission leaves lineage unstated) and `reference` (the original `schema.relation` the output must equal). |
| `register_obligation` | Validate one obligation, check source SQL against the estate, run a recompute grain probe, and accumulate it. Re-registering the same `obligation_id` replaces the prior item. Include an `abstention` string in the JSON when the obligation belongs to an ambiguity fork that cannot be committed. Optional `spec_item_ids` is a non-empty list of distinct structural `spec_id` values the obligation proves; when present, grading attributes it only to those items rather than inferring attribution from SQL. |
| `register_structurals` | The BULK form: several structural items in ONE call, `items_json` being a JSON LIST of the same item objects `register_structural` takes. It drives that tool per item rather than reimplementing its gates, so the contract is enforced in one place. The registration budget is charged per CALL, so registering a table's columns together costs 1 where one call per column costs N. In a derived build, the answer also includes `unchecked_column_items` when any column item has no check attributed to it; finalize refuses while items remain. |
| `register_obligations` | The BULK form of `register_obligation`: `items_json` is a JSON LIST of obligation objects, each resolution-checked and grain-probed exactly as a single registration is, with one optional `connection_id` for the batch. Each obligation still pays its own estate work — a batch of 50 obligations each naming two schemas performs 50 resolution checks and up to 50 grain probes, and those checks cost up to 200 metadata reads (two per distinct schema per item, never shared between items: a schema's relations can change mid-batch, and a cache across them would answer later items from a catalog the estate has moved past) — so bulk saves registration budget and turns, not queries. In a derived build, the answer also includes `unchecked_column_items` when any column item has no check attributed to it; finalize refuses while items remain. |
| `register_target_model` | Register the source-to-target mapping the PROPOSER supplied with the run (it takes no mapping of its own — the seat never writes one). It first checks the mapping against the source: it must parse, every column of every legacy table it carries must be carried into a target or declared dropped (a table declared loaded nowhere, `images: []`, is disposed of whole), every column it names must exist, every source a derived target is built from must exist and be named with one spelling, and each hub's business key must be unique and non-null on the source. For a link business key, an unqualified part such as `account_no` must match exactly one participating hub's key; a part that matches none or several is refused with the qualified `<legacy object>.<column>` forms to use. Qualified parts such as `account.account_no` are taken as written. The complete link key must give each participating hub one key part in participant order. A longer key must put those hub keys first, then name each dependent child once as `<legacy object>.<column>` on the junction; that column must be carried onto the link and must not be a participating hub's hash key or another key part. A missing hub prefix or invalid child is refused. Each rendered link's full key is also measured on its junction: if it repeats, the finding includes the source row count, distinct-key count, repeated-key count, and a dependent child to add; if any key part is `NULL`, that is a finding too. Such a non-identifying link key is returned to the proposer, because its `LNK-*` check could only answer `INDETERMINATE`; nothing is registered. A list of `{target, derivation, sources, grain, rule}` description rows is not a `target_model` object; see [Declared target mappings and Data Vault shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes) for the version-2 shape the tool expects. Every hub whose table and key columns are readable is probed even when another hub's probe fails, and every readable link probe runs independently; a failed probe returns one estate refusal naming all failed probes and carries key findings from probes that did run in `mapping_findings`. Any problem is returned as findings for the proposer and nothing is registered. The success response also includes `hubs_without_ghost_keys`: each hub with no declared `ghost_keys`, plus the `ghost_keys` declaration it would need if the ticket or mapping says its load inserts a placeholder row; a hub loaded with no ghost is correct as returned. When it holds, the mapping becomes the spec's `target_model`; version-2 plain images can declare load-derived columns in their own `metadata_columns` (see [Declared target mappings and Data Vault shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes)). A version-2 image with no vault role, fed by multiple legacy objects, can declare `key` as the image columns identifying its rows; every feeder declares the same `key` and maps one of its own columns into each key column. This renders an `M-<image>` check against the union of the feeders' key sets. A historized image may declare `history` with `relation` and `batch_column` (and a non-vault image also supplies `history.key`), which renders an `H-<image>` history obligation against the source's per-batch or versioned history. Alongside the `CS-*`, `M-HUB-*`, `LNK-*`, and `H-*` obligations, it renders `M-<image>` row-membership obligations for satellites, links loaded from a hub's own legacy object, and plain images that have a usable declared key; these compare distinct business-key sets and are registered through the same door as `register_obligation`, stamped `rendered_from: target_model`. The mapping owns those ids: a hand-written obligation under one is refused, and a rendering it no longer produces is retired. A sole image carried one for one is covered by the current-state row-count comparison and, where both tables were digested, by content comparison over its carried columns; an image that cannot be keyed — including a merged image without a declared `key` or a plain image without a declared key — is returned in `unrendered` with the named reason rather than silently treated as matched. An image without a source history is reported in the grade's `history_not_testable` list rather than treated as matched. The completed grade persists that list and names the affected objects in its verdict headline; see [Declared target mappings and Data Vault shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes) for the presentation contract. `finalize_spec` refuses a run commissioned with a mapping until it is registered. Cost: one catalog read per legacy table the mapping names, one aggregate query per hub business key and one per rendered link key (the link probe scans its junction joined to each participating legacy object), and each rendered obligation's resolution check and grain probe. |
| `register_time_value_binding` | Bind a ratified STRING `HH:mm:ss` TIME target column to the source value and row keys used by its seal-owned value check. See [parameters and behavior](#register_time_value_binding). |
| `register_settlement` | Re-run a read-only grounding query for an estate-resolved ambiguity and retain its measured result as sealed provenance. |
| `register_substrate` | Record the build mechanism and constraints the ticket states, as an optional `SUBSTRATE` section. Re-registering replaces the thread's prior substrate clauses; the section states no obligation and is not graded. |
| `register_accepted_differences` | Record the estate-wide difference CLASSES the ticket accepts, as the artifact's `accepted_differences` key — a `type_mapping` (declared source→target type pairs) or a `value_substitution` (a source literal, what it becomes, and the SOURCE column types it applies to). The grade licenses a column-grain difference the class covers and reports the rule's own id on it. An eligible passing membership check can also license the literal-to-NULL substitution it asserts on its compared column; see [checked substitution grading](/docs/Genesis-Prover/Agents-And-The-API#checked-substitutions). A numeric mapping into a scale-zero type that could lose fractions is sealed with `condition: "whole_numbers"`; the reply lists these pairs in `whole_numbers_only` as `rule_id: source_type -> target_type`. A mapping into a type that holds fractions, such as `NUMERIC -> DOUBLE`, needs no condition; see [type-mapping behavior](/docs/Genesis-Prover/Overview). See the [compiled-grade API contract](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled) for how the grade checks the `whole_numbers` condition. Takes the whole set in ONE call, keyed on `rule_id`; all-or-nothing, because a partly applied set leaves a class the author believes is accepted grading as drift. A rule never licenses by object name and never licenses a missing row, table or column. |
| `register_clause_accounting` | Account for every commissioned numbered clause and table row (ticket keys use `'<list>.<number>'` or `'T<table>.<row>'`; asset keys include the asset name). `accounted_by` accepts `obligation` (refs naming proving `obligation_id`s), `scope` (refs naming objects the comparison is intended to prove, including a dataset with no table schema measured file by file; since v9.33), `accepted_difference` (refs naming licensing `rule_id`s), `not_applicable` (a note explains why the clause commissions nothing here, grounded by `evidence` measured on the source or by the `ruling_id` of a clarification the run was commissioned with), or `open` (not yet provable). A `scope` entry records the basis, not a pass: the grade decides whether every named object was measured on both sides and compared clean; see [scope clauses in a grade](/docs/Genesis-Prover/Agents-And-The-API#the-spec-author-seat). An `open` entry requires `reason`: `reference_unreadable` (refused, as `open_on_file_measured_object`, on a dataset the latest source scan measured file by file), `rule_unstated`, `name_missing`, `pairing_key_missing`, or `estate_unreachable`; `remedy` with `actor` `proposer`, `owner`, or `operator`, `kind` `declare_key`, `land_reference`, `state_rule`, or `name_column`, and a one-sentence `statement`; and a non-empty `evidence` list of `{sql, result}` string pairs. Optional fields are `depends_on` (string list), `remedy.options` (string list), `remedy.measured_candidate`, and `remedy.recommended_answer` (a one-sentence recommendation, required when `actor` is `owner` or `operator`; when `options` lists alternatives or the statement contains “or”, recommend one and say why). For an owner or operator remedy, the statement and recommendation are checked for Prover terms; wording findings explain the required rewrite. `mapping_entry_contested` and remedy kinds `supply_mapping` and `restate_entry` are reserved and refused because mapping findings decline the run. A partial seal must seal at least one clause. Entries accumulate by clause; at most 100 per call, and each reply names clauses still open. Do not submit ledger entries if no numbered item or table row was commissioned. |
| `add_lean` | Attach a committed `lean` to one already-registered obligation by id, changing nothing else about it. Runs no query. |
| `finalize_spec` | Validate the complete artifact — `spec_name`, `structural_items`, `obligations`, `notes`, plus `scope` and `accepted_differences` when the spec registered them — enforce the seeded-round diff, apply relation qualification, run the seal gates (among them, since v9.34, `target_design_column_undeclared`: a column the registered mapping lists in an image's `metadata_columns` that no column item declares), write the sealed files, and register the artifact by `spec_hash`. |

After finalization, inspect the terminal author-seat summary for `sealed_obligations`,
`clause_dispositions`, and, on a repair, `unapplied_removals`. The
[author-seat status response](/docs/Genesis-API/API-Reference#get-api-estate-spec-conformance-author-seat-run_id)
defines these fields and the persisted Registrar checkpoint order; the
[Prover repair guidance](/docs/Genesis-Prover/Agents-And-The-API#open-questions-and-provider-faults)
explains how to handle a removal that still needs the owner's ruling.

For the live table-accounting check applied to mappings made only of derived targets,
see [Declared target mappings and Data Vault shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes).

`register_target_model` also probes each declared reference whose source and referenced
columns are readable: one query scans the referencing object and checks each non-`NULL`
value against the declared referenced column. A reference with values but no matches is
returned as a finding; a reference column with no non-`NULL` values is not. Probe failures
join the other failed source probes. This adds one query per measurable declared reference,
with a correlated lookup of the referenced object per source row.

For how declared satellite history affects rendered link-membership checks and which history
columns must be present, see [Declared target mappings and Data Vault shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes).

`register_target_model` looks up the run's source and target engines before rendering; this
adds one indexed run lookup and, when `target_connection_id` is set, one connection-record
read. A mapping that needs engine-specific identifier quoting is rendered for that pair
only when the run places its target. Without a placed target, rename the identifier to a
plain name or place the target; a grade on a different engine pair refuses the rendering.
See [engine-pair renderings](/docs/Genesis-Prover/Overview#engine-pair-renderings).

### `withdraw_scope`

Withdraw entries that are wrong in kind, such as a legacy object scoped `same` before the
seat knew its declared target model splits it into images. This removes the object from the
spec's scope; it does not register replacement entries. Register each image separately with
`register_scope`. To correct an expectation rather than remove an entry, call `register_scope`
again for that object.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `objects_json` | string | required | A JSON list of object names exactly as registered in this thread. A JSON string is also accepted as a one-object list. Every name must already have a scope entry in this thread's draft. |
| `bot_id` | string or null | implicit | Derived from the acting agent context. |
| `thread_id` | string or null | implicit | The active authoring thread whose draft is changed. |
| `user_id` | string or null | implicit | Derived from the requesting user context. |

For example, pass `objects_json='["PUBLIC.ORDERS"]'` to withdraw one entry. The call is
all-or-nothing: if any named object has no entry, nothing is withdrawn and the response names
the missing objects. On success, the response includes `withdrawn` and the remaining
`scope_count`. This is in-memory only; it performs no estate query, connection read, or model
call.

### `load_prior_spec`

Use this tool at the start of a repair round to load the prior sealed artifact.
Address it by its `spec_hash` — the only address form, and the way every other
verb in this surface names a spec. A prior this deployment's store does not hold
is refused with the remedy that finishes: register the sealed artifact through
`POST /api/estate/spec-conformance/compiled`, then repair by the hash that
returns. It accepts only an empty draft, so call it before `register_structural`,
`register_obligation`, or `register_settlement`.
A run commissioned with `repair_of` seeds only from that seal, and any other hash is
refused. If the run-store lookup fails, the seed is refused whatever the run's tooling,
because which seal it may repair cannot be checked. Retry once the run store is readable;
if it stays unreadable, report the failure to the commissioning caller and stop. The store
error is logged but is not included in the reply. A readable store with no seat-run row for
the thread does not block seeding. When the seat run exists, its commissioned connection
is bound to an unbound draft as part of the same seed write, even if the repair only amends
or withdraws carried checks and registers no new check. An already-bound draft keeps its
connection. This keeps finalization on the connection the repair run was commissioned to
use. When there is no seat run, the prior's recorded connection is inherited instead; if the
prior also has no connection, seeding follows its parent seals to the nearest recorded one.
The inherited catalog placement is carried into the reseal when it is bound to that same
connection. A read failure while resolving this lineage leaves the draft unbound.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `spec_hash` | string | `""` | The `spec_hash` of the prior sealed spec this repair round starts from. The only address form. Read seal-verified from the compiled-spec store. |
| `prior_spec_hash` | string | `""` | Deprecated spelling of `spec_hash`, still accepted. Supplying both with different values is refused rather than guessed at. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Empty draft to seed for the active repair thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

When the active run was commissioned with `repair_of`, this tool accepts only that
`spec_hash`. Naming a different prior is refused before its artifact is read, and the
response directs the seat to the commissioned hash. Enforcing this binding adds one
indexed run lookup.

On success, the response reports the seeded `structural_items` and
`obligations` counts and `settlements_seeded: 0`, plus everything the round needs
about the prior artifact without opening its file:

Before reading the prior grade or sealing the artifact, the tool checks whether the
thread's draft is still empty. If it already contains registered work, the seed is
refused without those reads and the draft is unchanged. This is an advisory pre-check;
the seed repeats the binding check under its write lock, so work registered concurrently
can still make the seed refuse. When seeding succeeds, the prior-grade block is read once
and stored with the round; later reads of the draft use that fixed block rather than
re-reading the newest grade.

* `prior_notes` — the prior artifact's `notes`, verbatim.
* `settlement_drafts` — its `SETTLEMENTS` entries, each already in the shape
  `register_settlement` accepts. The notes grammar is written and parsed by one
  codec in the artifact-format layer, so what `finalize_spec` seals is what a
  later repair round reads back. A line that does not carry the four labelled
  parts is returned verbatim under `settlements_unparsed` rather than dropped.
* `settlements_note` — present only when no draft could be built, stating that no
  settlements were recorded. No empty list is returned in its place.
* `manifest` — every seeded `spec_id` and `obligation_id` with its locus, the
  relations it reads, its fork axis, and whether that axis is committed.
* `prior_grade_run_id` — the succeeded grade run that supplied the prior's latest
  grade reading, or `null` when no grade of this spec was found in the recent window.
* `prior_grade_unverified` — the obligations that grade could not decide, each with
  its `obligation_id`, `status`, `error`, and `cause`. An empty list means the grade
  read successfully and found nothing undecided; the field is omitted when the grade
  was found but its verdict coverage could not be read.
* `prior_grade_unverified_note` — explains whether the latest grade found no
  undecided obligations, recorded obligations it could not decide, or supplied no
  readable coverage. This reading is taken once while the round is seeded and does
  not change if a newer grade arrives mid-round; start a new repair round to read it.
* `clause_accounting_not_carried` — present when an entry could not be assigned a current
  document key: its old key is absent and its recorded wording could not be matched
  uniquely to an unused new key, or another carried entry already owns that key. Each entry
  retains the old `clause` key and clause text; an open entry includes its reason, remedy,
  and evidence. If the document still states that clause under a new key, register it under
  that key; a removed clause needs no re-accounting. `clause_accounting_not_carried_note`
  explains the case, including when the current document numbers no clauses.
* `clause_accounting_rekeyed` — present when carried entries match clause wording under a
  different key in the current document; each item has `from` and `to`. These entries are
  already seeded under the new key.
* `clause_accounting_reworded` — present when a carried entry's recorded words differ from
  the document's clause under the same key. Each item includes `now_reads`, the wording in
  the current document; check whether the entry still accounts for it and re-register it
  when needed.
* `clause_accounting_ungrounded` — present when a handed document includes a prior
  `NOT APPLICABLE` clause whose sealed note has neither a measurement that reads a name in
  the current clause nor an owner ruling still in force. These clauses are not in the draft.
  Re-account for each as `not_applicable` with evidence or a commissioned `ruling_id`, or as
  `open` with its reason, remedy, and evidence; the seal refuses any left unaccounted.
  `clause_accounting_ungrounded_note` explains this requirement.

`seat_settings_inherited` is present when the repair inherits an unset authoring setting;
it maps each adopted key to its `value`, `from_spec_hash`, and `default_was` value. When
`repair_of` names the prior and `authoring_tooling` was unset, submit inherits that seal's
tooling, so the run handle names the effective tooling from the start. The load also
reports that inherited setting. It inherits each `source_catalog` or `target_catalog` a
repair was commissioned without when the prior is loaded: each comes from the placement
the prior spec was sealed with, the source catalog only when the repair authors against
the prior's connection and the target catalog only when its target is on the prior's
target connection (`default_was` is empty for a catalog). A setting or catalog the caller
named is never changed.
`seat_settings_note` accompanies it with an explanation of the inheritance; if the tooling
becomes `classic`, the note says Registrar verbs are withdrawn and to use the classic verbs.

If the artifact cannot be
read, does not satisfy the sealed artifact contract, or the draft already has
registered work, the tool returns a rejection and leaves the draft unchanged.

### `register_substrate`

Record the customer's stated requirements for **how the change must be built**. The
section is optional: use it only when the ticket names a build mechanism, where the
transformations live, a re-run rule, or another constraint on how the copy is done. Do
not infer a mechanism from the estate or recommend one. The substrate states no
obligation and nothing in it is graded; it is sealed with the spec so a later building
agent can retrieve and certify against the customer's words.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `substrate_json` | string | none | One JSON object with `clauses`, a list of short statements in the ticket's own terms. Pass `{"clauses": []}` to record no substrate. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

The tool normalizes whitespace, accepts at most `25` clauses, and limits each clause to
`2048` characters. Empty clauses are rejected. Calling it again replaces the prior
clauses for that thread rather than adding a second contradictory section. The operation
is in-memory only; the clauses reach the sealed artifact when `finalize_spec` runs.

After sealing, read the section with `GET /api/estate/spec-conformance/compiled/{spec_hash}/substrate`.
That response distinguishes `declared: false` (the ticket stated no substrate) from an
empty clause list. After the build, the [spec-conformance API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-compiled-spec_hash-self-certification)
documents the separate statement surface: a declared substrate produces an anchored
`self_certification`, while `declared: false` records the builder's own substrate choices
or departures as `substrate_declaration` with `anchored: false`. Neither record is a Prover
verdict.

### `list_draft`

Lists what the active thread's draft holds — counts, the bound `connection_id`,
and the same manifest `load_prior_spec` returns. Use it mid-round to recover the
ids to address. It returns no SQL bodies: repair an item by re-registering its
id, commit a fork member with `add_lean`, and every untouched item is carried
into the new seal unchanged. A thread holding no draft receives zero counts and
an empty manifest, not a rejection.

By default it returns every section. Pass `sections` to request only the sections
you need — for example, `sections: ["counts"]` requests just the counts (a
no-draft response also includes its explanatory `note`). The
available sections are `counts`, `connection_id`, `structural_items`, `obligations`,
`fork_axes`, `settlements`, `prior_grade`, and `reseal_preview`. An empty list or
any unknown section is refused. `structural_ids` filters the `structural_items`
manifest list by `spec_id`; `obligation_ids` filters the `obligations` list by
`obligation_id`. Counts always describe the whole draft, and each returned fork
axis always includes all its members.

On a round seeded by `load_prior_spec` it also carries `reseal_preview`, the
repair dry run: obligation and structural counts `before` and `after`, the prior
ids this draft no longer holds and the ones it added, per-`kind` counts on both
sides, and `shrank`. A round that dropped obligations while editing something
else sees it here, before anything is sealed.

The draft's connection binding is also included in `connection_id`. If `load_prior_spec`
bound an unbound draft to the commissioned seat run's connection, this is the connection
used when the repair finalizes, including a round that only amends or withdraws carried
checks.

`edited_obligations` is the other half: every obligation the round CARRIES
FORWARD with a changed field, each field with its `before` and its `after`, read
off the same walk the seal gate refuses on. Where the edited field is a
`source_sql` body, the entry also carries `movement` — the prior body and this
one, each run once against the bound estate, joined on the obligation's keys,
and compared using the grade's [declared-column rules](/docs/Genesis-Prover/Overview).
`columns_missing` lists declared compared columns neither body projects. It reports
`rows_changed`, `max_delta` with
its column and key, `keys_dropped` / `keys_added`, `columns_compared` /
`column_tolerances`, the rows whose movement one form's tolerances admit and the
other's do not (`rows_closer` / `rows_farther`, with a `verdict_basis` saying
these are the two SOURCE forms and not the source-vs-target verdict). An edit whose
movement was not measured says why instead of
reporting zeroes — a tolerance edit on an unchanged body moves no row on the
source side, because the seat never executes `target_sql`.

`preview_licensed_edits: true` says the edits are reported; whether one was
LICENSED is still decided at `finalize_spec`, against the name pass's own
receipts. A freshly authored draft carries no `reseal_preview` — there is no
prior, so there is no denominator.

On a repair round, `list_draft` also returns the `prior_grade_run_id`,
`prior_grade_unverified`, and `prior_grade_unverified_note` from the grade reading held
when `load_prior_spec` seeded the draft. It does not perform a second grade lookup, so
the repair inputs remain fixed for the life of the draft; start a new round to pick up a
newer grade.

**Cost.** A call that leaves `reseal_preview` out reads one copy of the in-memory
draft only — no estate query, file access, or grade lookup. Including
`reseal_preview` assembles the artifact that `finalize_spec` would seal. On a
repair round that edited a `source_sql` body, it also pays one connection-record
read and then two statements per edited obligation (one where both forms share a
body), capped at 10 statements and 2,000 rows each per call; edits past the cap
are reported with their movement unmeasured.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `sections` | list of strings | none (all sections) | Sections to return: `counts`, `connection_id`, `structural_items`, `obligations`, `fork_axes`, `settlements`, `prior_grade`, and/or `reseal_preview`. Empty or unknown section lists are refused. |
| `structural_ids` | list of strings | none (unfiltered) | `spec_id` values to include in the `structural_items` manifest section. Counts still cover the whole draft. |
| `obligation_ids` | list of strings | none (unfiltered) | `obligation_id` values to include in the `obligations` manifest section. Counts and all members of each returned fork axis still cover the whole draft. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

### `register_structural`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `item_json` | string | none | One JSON object with `spec_id`, `locus`, `change_kind`, `description`, `expected_effect`, and `change_expectation`; it may also include `expected_type`, `expected_type_family`, and `expected_scale`. Set `change_expectation` to `must_differ` when the target must change at the locus, or `must_match` when the target must retain it unchanged (for a lift-and-shift or landing hop). Include `type_license` as `"ticket"` or `"inferred"` when any type declaration is present. For derived builds, optional `inputs` lists source-coordinate lineage (`{ "locus": "schema.relation[.column]", "role": "value\|key\|filter\|join\|rowset" }`, or plain locus strings); `[]` declares a constant. Optional `reference` names the original `schema.relation` the output must equal. In a derived build the item's `locus` is the output in target coordinates. For the grading effect of `change_expectation` on a sole one-for-one image, see [the Prover's target-mapping rules](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes). `change_kind` must be one of `add_column`, `drop_column`, `rename_column`, `type_change`, `transform_values`, `add_table`, `drop_table`, `add_derived_mart`, `modify_etl_derivation`, or `drop_constraint`. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

For how an object-level `add_table` item is decided when its legacy object is split, see
[the Prover grade overview](/docs/Genesis-Prover/Overview#3-spec-conformance-the-spec-agent-and-the-grade).

For a `drop_constraint` item, put the key being removed in `description` or
`expected_effect`: the grader confirms only a named key kind (`PRIMARY KEY`/`PK` or
`UNIQUE`) and, when supplied, its column list. Use `UNIQUE` with a key indicator such as
`UNIQUE (email)`; the ordinary word “unique” does not name a key. The wording must name
only one key kind and at most one column list. If it names no key or is ambiguous, the
item remains indeterminate; if a different key was removed, it is not implemented. See
[the Prover grade overview](/docs/Genesis-Prover/Overview#3-spec-conformance-the-spec-agent-and-the-grade)
for when a confirmed key removal meets a `changed` scope entry.

Once the scope is registered and makes the spec a derived build, `register_structural` and
`register_structurals` refuse an item whose `inputs` name neither a scope entry nor an output
of the spec, with the finding finalization would give, and write nothing for that item.
Register the input as an `input` scope entry first. An item registered before its scope is
still judged at finalization.

### `register_obligation`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `obligation_json` | string | none | One JSON obligation. Comparison kinds require `obligation_id`, `kind`, `title`, `rationale`, `source_sql`, `target_sql`, and a non-empty `keys` list. Optional `relative_tolerance` is a finite, non-negative number expressing a fraction of the larger compared value; keyed comparisons match within either this relative bound or the absolute `tolerance`. `target_sql` may spell the graded deliverable as `target_catalog.schema.table` (or include a column); grading attributes that spelling to the matching structural item when `target_catalog` names the same catalog. Recomputes also require `grain_probe`; invariants use `relation` and an `invariants` list. Optional `spec_item_ids` is a non-empty list of distinct structural `spec_id` values the obligation proves; when present, grading attributes it only to those items instead of inferring attribution from SQL. A comparison obligation may include the `owning_relation` string: the one table the check is about, which its SQL must read. A height, key or grain check (every statement returns summary rows: a count, a distinct-key count, a violation count or a total) must carry it, or link that table's structural item with `spec_item_ids`; registration refuses one that names neither (constitution v9.32). In a composed spec set, the check moves to that member only when exactly one member owns the named relation; otherwise it remains with the author. If omitted, it remains with the author. A `written_by` obligation uses `relation` plus `writer`, where `writer.mechanism` is one or more of `job`, `notebook`, or `pipeline`, with optional `notebook_path_prefix` or `job_id` narrowing the named mechanism. It has no source/target SQL pair. The rationale must include a line beginning `this catches:`. For an unresolved ambiguity fork, optionally include `abstention` as free-text explaining why the axis cannot be leaned. `kind`, when present, must be one of `membership`, `recompute`, `self_consistency`, `invariant`, or `written_by`; use `null` only when the artifact contract permits an omitted kind. |
| `connection_id` | string | `""` | Named database connection used for source checks and grain-probe execution. Required on the thread's first registration — there is no default estate — and omitted afterwards to reuse the connection that registration bound. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

For the allowed `kind` values and the grading behavior for an unknown non-null value, see
[how agents drive the Prover](/docs/Genesis-Prover/Agents-And-The-API#graded-obligations).

In a derived build, a `membership` or `recompute` check that reads an output which must equal
its reference, and that reference, is answered with `value_coverage` while the output still has
columns no check compares with the reference: `columns_counted`, `why` when the check counts
none (for example, its `target_sql` cannot be read in the target engine's dialect, or its keys
are not columns it reads), and every `uncompared_columns` entry. `register_obligations` lists
each such note under its item.

For a recompute with a constant expected side, or an invariant on a referenced output,
registration also runs the check's rule against the reference original. If the original
already violates that rule, registration refuses the check: a faithful build would fail
it too. A check is exempt only when the ticket orders the output to differ from its
reference; set `reference_contradiction_declared: true` and provide
`reference_contradiction_rationale` quoting (in double quotes) a sentence from the ticket
that states the rule. A quote not found in the ticket is refused before the estate is read.
When the reference cannot be checked, the accepted response gives the reason in
`reference_probe_unmeasured`; that does not refuse the obligation. This probe is read-only
and checks no more than 50 rows; a result over that limit is reported as unmeasured, not
compared partially.

`register_obligation` rejects an obligation when any executed SQL field
(`source_sql`, `target_sql`, or `grain_probe`) hard-casts a column from a raw or
staging relation. This includes qualified relations with a segment beginning
with `raw_` or `stg_`, or a segment named `raw` or `staging`, whether the
relation is referenced directly or through an alias. Use a tolerant parse such
as `TRY_CAST` or a `TO_*` function with a safe fallback instead; tolerant
parsing yields `NULL` rather than failing the statement on the first
unparseable value.

Registration also refuses an executed SQL field whose `NOT IN` subquery can
yield `NULL`: SQL then never evaluates the predicate as `TRUE`, so an
unmatched-row check can count nothing and pass vacuously, while a `grain_probe`
measures nothing. This check covers `source_sql` and `grain_probe` in the
source connection's dialect, and `target_sql` in the placed target engine's
dialect; when no target dialect is available, it checks `target_sql` as ANSI
SQL instead. Rewrite the predicate as correlated `NOT EXISTS` or a `LEFT ANTI
JOIN`, or filter every selected subquery column with `IS NOT NULL` (qualified
with the subquery's alias when it joins multiple tables). A repair that
re-registers a field unchanged from its seal is not checked again for this
rule; edited fields are checked normally.

Before resolution checks and probes, `register_obligation` refuses a comparison
with `check_measures_nothing` when neither `source_sql` nor `target_sql` measures
a relation. It also refuses when `owning_relation`, or the loci linked by
`spec_item_ids`, name the asserted object, a non-measuring statement reads it,
and every measuring statement reads only other relations. A `FROM`, CTE, or
derived table that supplies only fixed rows does not make a typed value a
measurement. Keep a literal on at most one side and make the other query the
object; in a migration, it can query the same-named source counterpart. The seal
repeats this check for carried obligations too. A statement the SQL reader
cannot parse is not judged. Re-register the obligation under the same
`obligation_id` with the fix named by the finding, then finalize again.

A source-anchored statement that reads a relation the draft's own structural
items declare created — an `add_table` or `add_derived_mart` locus — cannot be
PLANNED, because the relation does not exist until the build runs. It is not
taken on the declaration alone: the relation must also be scoped `new`, and must
be absent from the estate's measured catalog. Only then is the statement
deferred, and the response carries `resolution_deferred`, one entry per
(statement, relation) pair — a statement reading two created relations yields two
entries — naming the relation, the declaring `spec_id`, and which of the two
checks actually ran for it.

The deferral is per **relation**, not per statement: every OTHER relation the
statement reads is checked against the measured catalog, because no probe will
see them. A create the scope does not hold as `new`, and a `new` object the
estate already holds, are both refused by name.

On a run whose target is on another connection or in another catalog,
`finalize_spec` prepares each deferred `source_sql` and the violation count for
each invariant still graded on the source against the source engine, using the
same no-read resolution form. If the source engine reports that a declared
build-output relation is missing, sealing is refused with
`source_reads_target_only_relation`; the finding names the obligation, relation,
and engine error. For an invariant, it also says to declare
`invariant_side: "target"` so the check asserts about the build. This check is
skipped when the build is in the source's own connection and catalog. It adds
one live source-engine round trip per deferred source-side statement on a
separate-target run. For a check between two derived tables, put the comparison
on the target side only; when reconciling against the source, read the source
relations the derived table is built from.

For an `invariant` whose `invariant_side` is omitted, registration records
`invariant_side: "target"` when the declared target model builds the relation, the
resolution check deferred it as a created relation, and the source catalog was
measured without that relation. The response includes `invariant_side_inferred`
with `side: "target"` and the basis for the inference, so the invariant is graded
on the build rather than against the legacy source. This inference is not made
when the source catalog could not be measured or the relation was not probed.
When the target model builds the relation but the source also holds a relation of
that name, registration refuses the unsided invariant because either estate could
be intended; resubmit with `invariant_side: "target"` or `invariant_side: "source"`.

On successful registration of a newly authored `membership` obligation with no `root_axis`,
the tool sets `root_axis: "population"` and returns `root_axis_defaulted: "population"`. An
explicitly declared valid axis is retained, and seeded declarations carried unchanged into a
repair are not defaulted again.

This covers a check over an upstream model of the same build. An obligation whose
source side reads the relation its own target side reads is also refused, but the
finding distinguishes two cases. If the spec declares that relation created and the
bound estate does not hold it, the source reads the post-build world; read the source
inputs (or the original named by the item's `reference`) instead. If the bound estate
already holds the relation, it is not a created output: remove the create-declaration
and re-scope it `changed` or `same`. These are declaration/scope faults, not spelling
faults; the response gives the corresponding remedy, including when both kinds of
fault occur in one registration. For `self_consistency`, the declared `relation` is
its target relation for this check, even when `target_sql` does not read it. A read of
an absent relation the spec does not declare is still rejected with the estate's own
error.

If the connection drops before an obligation's SQL or grain probe is evaluated,
the response is retryable rather than a modelling rejection: it includes
`retryable: true`, `rejected: false`, and a hint to call again with the same
payload. The same transport classification applies when `register_settlement`
executes `grounded_by_sql`; a dropped connection is not evidence that the SQL or
the settlement is wrong.

When the registered query transport cannot be opened, `register_obligation` does
not reject the obligation only for that reason. It records the statement in
`resolution_unprobed`, accepts the obligation without claiming that the statement
was checked, and reports any source relations without a receipt in
`relations_unobserved`. Before finalization, read those relations with an
available tool: re-register the obligation when its resolution or grain probe
can run, use `register_settlement` for an executed grounding query, or let the
finalize-time catalog read observe a relation's returned columns. A successful
empty result is not a `sample_read` receipt.

### `register_time_value_binding`

Register the source binding for each declared TIME column ratified for STRING
`HH:mm:ss` storage, and for each such encoding carried into a repair round. The target
relation and column must match this run's declared target types or a carried encoding.
The seal builds and owns the keyed check from this binding; do not register a `TV-` check
yourself. A repeated call for the same column replaces its earlier binding.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `target_relation` | string | required | Target relation, exactly as listed in the run's target column types. |
| `target_column` | string | required | TIME target column whose STRING `HH:mm:ss` storage was ratified. |
| `source_relation` | string | required | Relation containing the source time value. |
| `source_column` | string | required | Source column holding the time value in the form declared by `source_form`. |
| `key_columns` | string | required | JSON array pairing source and target rows. Use a column name when both sides share it, or an object such as `{"source":"EVENT_ID","target":"ID"}` when names differ. |
| `source_form` | string | required | How the source column spells a time: `hhmmss_text` (six-digit text such as `140509`), `hh_mm_ss_text` (text already `HH:mm:ss`, such as `14:05:09`), or `native_time` (a TIME column). Values are checked only in the declared form; another spelling fails grading. A six-digit numeric column is not supported because casting can drop leading zeros. |
| `connection_id` | string | `""` | Named connection used to read the source. Required on the thread's first `register_*` or `register_settlement` call; later calls reuse the bound connection when omitted. |
| `bot_id` | string or null | implicit | Derived from the acting agent context. |
| `thread_id` | string or null | implicit | Active authoring thread whose draft is changed. |
| `user_id` | string or null | implicit | Derived from the requesting user context. |

For example, bind `PUBLIC.EVENTS.START_TIME` to six-digit text in
`PUBLIC.RAW_EVENTS.START_TIME` on `EVENT_ID` with `source_form="hhmmss_text"` and
`key_columns='["EVENT_ID"]'`. The source value is compared with the stored target text,
along with a hidden validity marker; malformed values, values in another form, mismatches,
one-sided `NULL`s and fractional seconds fail grading. For `hhmmss_text`, `000000` is
marked `unruled_initial` and fails: it can mean midnight or no time recorded, and passing
it requires a person's ruling. A carried binding without a declared source form must be
registered again; no form is assumed. `finalize_spec` refuses a missing binding
(`target_time_value_check_missing`) or a held check that is not the current rendering
(`target_time_value_check_stale`), and retires checks for encodings no longer ratified.
Unsupported engines or zoned TIME columns are refused by name. If an engine cannot render
a check, finalization sends the refusal to the commissioning caller even when that check
is already held; it does not ask the author to register a binding the seal cannot use.
SQLite source checks validate six-digit `hhmmss_text` in UTF-16 databases as well as other
SQLite encodings. Source checks support BigQuery, Databricks, PostgreSQL and SQLite; target
checks support Databricks and SQLite. SQLite checks reject time text with NUL-hidden trailing
bytes; see the [Prover's SQLite time-text rule](/docs/Genesis-Prover/Overview#3-spec-conformance-the-spec-agent-and-the-grade).

Cost: one run-row read, two connection-record reads and the source resolution check;
each registered check adds one keyed comparison per grade, reading the bound source
columns and target columns.

### `register_settlement`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `settlement_json` | string | none | One JSON object with `question`, `chosen_reading`, and a read-only `grounded_by_sql`; optionally include `axis` (a stable name for the ambiguity, defaulting to `question`) and `obligation_ids`. The query is executed and its result is stored with the settlement. Reusing the same `axis` replaces the earlier settlement on that axis. |
| `connection_id` | string | `""` | Named database connection used for the grounding query. Required on the thread's first registration — there is no default estate — and omitted afterwards to reuse the connection that registration bound. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

`register_settlement` returns the measured `grounded_result`, `axis`,
`settlement_id`, and `settlement_count`. When a settlement replaces an earlier
one on the same axis, it also returns `replaced_previous: true` and
`previous_settlement_id`; use the same `axis` to correct a settlement instead of
registering a rival entry.

### `declare_migration_shape`

Use this deterministic repair when a grade reports structural items as
`indeterminate` because their migration shape is undeclared. The REST contract and
refusal conditions are documented in [Declare migration shape](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-compiled-spec_hash-declare-shape).

| Parameter | Type | Default | Description |
| - | - | - | - |
| `spec_hash` | string | none | The 64-character hexadecimal hash of the sealed specification to derive from. |
| `change_expectation` | string | none | Required migration shape: `must_differ` for a change specification, where the target must differ from the source at each locus; or `must_match` for a lift-and-shift or landing hop, where the target must contain each locus unchanged. |
| `item_expectations` | object | `{}` | Optional `spec_id` to shape map for layered moves whose items ask opposite questions. Overrides `change_expectation` only for the named items. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Derived from the acting agent context; not used as a run handle. |
| `user_id` | string | implicit | Derived from the requesting user context. |

The response contains the new `spec_hash`, its parent, and a `declared` receipt
with the value written, item count, and item overrides. Grade with the returned hash.

### `add_lean`

Commits an ambiguity fork by attaching a `lean` to one member already in the
draft, addressed by `obligation_id`. It writes only that field, so no SQL,
tolerance, key, rationale, or reading can change through this path — which is
what lets a repair round commit a fork whose member bodies it has never read. It
runs no estate query, because nothing new is submitted. Use it instead of
`register_obligation` whenever the lean is the only thing being added.

Fork membership is read through the seal gate's own grouping, so this tool cannot
accept a lean on an obligation R1 does not regard as a fork member.
For grade-result interpretation, see [what a run reports back](/docs/Genesis-Prover/Agents-And-The-API#what-a-run-reports-back).

| Parameter | Type | Default | Description |
| - | - | - | - |
| `obligation_id` | string | none | The fork member being committed, exactly as `list_draft` or `load_prior_spec`'s manifest reports it. The tool never creates an obligation: an id the draft does not hold is rejected, and so is one that belongs to no multi-member `ambiguity_group` — a lean commits one reading of an axis, and on an ordinary obligation it names nothing. |
| `lean_json` | string | none | One JSON object with a non-empty `reading` naming the reading committed to; `justification` and `prior` are optional. A value that names no reading is rejected — record an `abstention` on the member instead. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

### `finalize_spec`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `spec_name` | string | none | Short name for the sealed spec and its artifact identity. |
| `amendments_json` | string | `""` | JSON list of deliberate changes to a prior seeded draft. Each object requires `obligation_id`, `field`, and a non-empty `basis`; include `from` and `to` to describe the transition. A carried obligation's field can be reworded by `to` without re-registering its body; its id and other fields stay unchanged. Name an ordinary deleted obligation or structural item with `field: "<deleted>"`. On classic repairs, a carried obligation can instead be removed under a commissioned owner clarification by naming its `ruling_id` in that deletion amendment; see the repair guidance above. |
| `round_kind` | string | `"qualify"` | `"qualify"` permits only relation-name qualification and refuses weakenings or deletions; `"authoring"` permits deliberate weakening or deletion only when declared by an amendment with a basis. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft to assemble and seal. |
| `user_id` | string | implicit | Recorded as the front-door registration operator. |

Before sealing, the draft must carry a row-set claim. A lift-and-shift, whose
scope asserts no `changed` or `new` object, must include at least one obligation
with `kind` set to `membership`; its keyed `same` scope entries do not replace
it. Any other draft must include such an obligation or a `same` scope entry
carrying `row_identity`. This row-set claim must state which source rows must appear in
the target by providing `keys`, `source_sql`, and `target_sql`; without it,
`finalize_spec` rejects the draft because the spec cannot detect rows dropped
from or invented in the target.

For an estate that is not multi-member, when complete latest source and target
scans are available, `finalize_spec` also refuses a carried `same` or `changed`
scope entry if neither snapshot can resolve its object name. Nothing is sealed:
use the name held by the scans (for a Foundry dataset, its RID or scanned name;
for a table, its schema-qualified name), then finalize again. This catches a scope
the proof could only grade as unmet; see \[scope verdicts]
(/docs/Genesis-Prover/Agents-And-The-API#scope-verdicts) for the grading behavior.

A `locus` or `relation` written `<database>.<relation>` is also refused, naming
the schemas of the bound connection to write instead. A spec is graded against a
build that does not land in the database it was authored against, so a
database-qualified name can never resolve there. The three-part form is
normalized rather than refused; a head that is neither the bound database nor a
known schema, and an unknown schema list, both pass.

On a round seeded by `load_prior_spec`, the seal reports `coverage`: obligation
and structural counts `before` and `after`, the ids dropped and added, per-`kind`
counts, and `shrank`. `counts` alone is unreadable on a repair, because "25
obligations" is a whole spec or an amputation depending on what the prior held.
The registration declares that prior as `parent_spec_hash`, which puts it under
the compiled-spec front door's own coverage gate — and the block reported here is
the one that gate measured, carried through with its `coverage_basis`, not a
second measurement taken by the seat. Where the store reports no measurement, so
does the seal.

**A refusal from that gate fails the round.** If the store judges the registration
and says no — a shrink with no stated basis, a declared parent it does not hold, a
declared parent that contradicts the stored lineage — `finalize_spec` records the
round failed with the store's own basis and publishes nothing, so the staged files
never become the sealed spec. An infrastructure failure is the opposite case and is
non-fatal: the artifact is good, the store is merely behind, and the response says
`REGISTRATION_FAILED` with the manual registration path.

After the artifact contract passes, `finalize_spec` also runs the seal gate's
lint rules and refuses to seal when they report a refusal. For an uncommitted
fork, either commit the member you choose with `add_lean`, or record the
abstention and why the axis cannot be leaned; then finalize again.
For comparison obligations (`membership`, `recompute`, and `self_consistency`),
the dated R9 rule refuses a seal when `source_sql` has a top-level `LIMIT n` and
`target_sql` establishes more than `n` rows through top-level `UNION ALL`
branches, each an unconditional aggregate. In that case, the expectation cannot
state a value for every target key; add an expected row for each key or narrow the
target query to the keys the expectation covers. The rule does not infer a target
row count when those branch conditions are not established. Artifacts not stamped
`2026-10-13.an-expectation-covers-every-key-it-grades` or later receive a review
finding rather than a refusal.
Before sealing, Genesis reads and verifies the pinned spec-author constitution
from the assigned skill package; if it cannot load or verify that digest, no
artifact is written or registered.

For a fresh Registrar authoring round, constitution v9.27's F1-D seal gate applies
when the scope contains any `input` entry or the registered target mapping declares a
derived target. It refuses a derived build whose structural tier is empty, an item whose
locus is a scoped input or is not read by its linked checks on `target_sql` (unless
the mapping declares that derived target), and an ordered output without a column
item. It also requires column items for output columns the checks key or compare on a
single target relation, target-side invariant columns, and columns declared by the
derived mapping. Link each obligation to the structural items it proves with
`spec_item_ids`; if an obligation links none, the gate evaluates each item against
all obligations. `same` scope entries cannot name an output; a `changed` output must
be read by a check on the source side or it is refused as absent from source. Scope
an output `new`, except an image carried under its legacy object's name, which is
`changed`; put source lineage in each item's `inputs`, and name an original to
reproduce in the object's `reference`. A copy (no `input` and no derived target)
does not acquire this structural-item requirement. Repair rounds are not re-judged
by F1-D. These findings are returned with the other seal findings; nothing is sealed
until corrected.

When a commissioned draft declares `target_model`, finalization refuses with
`carried_column_added` if a structural `add_column` item names a column the model
carries from a source into an image with a different name. `add_column` is decided
against the same-named source object, which does not exist for that image, so the
grade can never decide the item. Drop it; if the ticket requires a property of the
column, register an `invariant` or `recompute` obligation that reads it on the
image. On a prior-seeded round, declare the deletion in `amendments_json` with
`obligation_id` equal to the item's `spec_id`, `field: "<deleted>"`, `from`, `to`,
and a `basis` naming this finding, and use `round_kind: "authoring"`. Nothing is
sealed on refusal.

On a fresh Registrar round, constitution v9.34 also refuses with
`target_design_column_undeclared` when a registered target mapping lists an image
column in `metadata_columns` but no column structural item declares it. The check
does not apply to repair rounds or images assigned a vault role. A column item
declares the image column by its `locus`, a rename's `new_locus`, or a
`propagates_to` entry; a removal item does not declare it. Register an `add_column`
item with source-column `inputs` (or `inputs: []` when the design gives it no source
input), the design's `expected_type` and `expected_type_family`, and a linked check
where one can be written. Use a recompute check for a computed column and a
population check for a column with no source input. Nothing is sealed until every
reported column is declared.

Finalization refuses with `carried_column_item` when any other column item on such a
carried column cannot be decided: a `transform_values`, `modify_etl_derivation` or
`type_change` item, or an item declared `must_match`, that no obligation reads at the image
(the grade compares a column item with the same-named source object, which does not exist,
so only the item's own checks can decide it), and any `drop_column` or `rename_column` not
declared `must_match`, which contradicts the carry. An item whose checks include one the
degeneracy probe measures degenerate on the source (empty, all-NULL, all-zero) is refused
too, naming the check and the probe's rule: the grade voids such a check, so it decides
nothing. The seal runs that probe, one read-only source query per such check, only over the
checks that alone keep a carried item sealable. State the claim as an obligation that
reads the column on the image, or drop the item, with the same deletion amendment on a
prior-seeded round.

Finalization refuses with `invariant_grades_nothing` when an `invariant` obligation declares
no constraint the grade counts: every rule is `finite` only (recorded, never counted) or
names no column. The grade builds no violation query for it, so it would error on every
proof. Record a limitation in the spec's notes or `history_not_testable` instead, or give
the invariant a counted constraint (`not_null`, `min`, `max`, `allowed_values`).
For `allowed_values`, a text value is compared as text even against a numeric member: text
`"01"` does not match numeric `1`.

Finalization refuses with `written_by_without_write_history` when a `written_by` obligation's
target engine has no per-relation write-history query (`writer_history_sql` is `None`). Such
an obligation would error on every build, including a correct one; a Flow-run record cannot
replace write history the engine does not expose. Drop the obligation, or, if this round was
seeded from a prior spec, declare its deletion in `amendments_json` with `round_kind:
"authoring"`. If the producer requirement still matters, record that this target cannot
evidence it in the spec's notes instead of making it an executable check. Nothing is sealed
on refusal.

On a commissioned run with `target_model`, finalization also refuses an `input` scope that
the mapping does not declare as read. The mapping must list the object in a split with
`images: []`, as a source of a derived target, or as a relation declared in an image's
`history`; an object carried into an image is not an `input` under this check. An input that
exists only in the target catalog is treated as a target-side relation read by the build
and does not need a source-to-target mapping entry. The refusal uses `undeclared_input`,
reports the objects that do not agree, and leaves the draft unsealed for the proposer to amend.

Finalization also refuses with `same_over_split` when `scope` expects `same` for a source
object that `target_model` splits into one or more images. Drop that object's `same` entry
and register each declared image, citing its mapping row: an image under a new name with
expectation `new`, and an image that keeps the source object's name with expectation
`changed`; then finalize again. The seal is not written on refusal. Once
`register_target_model` has registered the mapping, `register_scope` refuses such a `same`
entry at the call under the same rule and writes nothing from that batch, including when an
image keeps the source object's name. This catches the mismatch on the first scope
registration rather than waiting for finalization.

Finalization also refuses with `new_over_carried_image` when `scope` expects `new` for an
image `target_model` carries a source object into under that object's own name. The source
already holds that name, so the build does not create it, and every check reading the source
object on its source side would be refused as reading the build. Scope it `changed`: on a
split the grade reads `changed` as it reads `new`, every image on the target. Once the
mapping is registered, `register_scope` refuses such an entry at the call under the same
rule.

For a fresh Registrar round's derived build, finalization also refuses under
`derived_build_items` a column item the grade attributes no check to (a removal excepted,
which the diff confirms; a column the value floor names is refused under
`declared_rules_unchecked` instead): a check whose
`spec_item_ids` name only an object item reaches none of that object's column items, and an
item with no check reads unverified on a correct build. Each finding names the check that
reads the column and the item ids to add to its `spec_item_ids`, or the item no check reads.
`register_structurals` and `register_obligations` return the same list as
`unchecked_column_items` while any remains.

For column items outside the value floor, this gate also requires an attributed check: a
check with `spec_item_ids` naming only an object item does not reach that object's column
items. When a check reads a column but omits its item id, the finding names the check and
asks to add the item ids; when no check reads the column, it asks for a check linked to the
item. Removal items are confirmed by the diff, and items already covered by the value-floor
rule are handled under `declared_rules_unchecked` instead.

Finalization also refuses with `excluded_but_delivered` when `scope` expects `excluded` for
an object `target_model` delivers: a source object it splits into one or more images, or an
object it declares on the target (an image, a vault entity, a derived target). The grade
reads either entry as unmet on a correct build. Drop the entry and scope each image: `new`
for an image under a new name, `changed` for one that keeps the source object's name;
unnamed target objects are reported as `scope_unclaimed` when the scope does not claim the
whole target, or as blocking surplus when it does.
`excluded` remains valid for an object the mapping loads nowhere.

On a commissioned run with `target_model`, finalization also refuses with `unrendered_link`
when a declared link renders no membership check. The finding names each link and source and,
when a participant is unreachable, the missing reference to declare. Fix the proposer-owned
mapping and retry; do not register a hand-written check in place of the model's missing check.
For reference spelling, including schema-qualified split names, see [Declared target mappings
and Data Vault shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes).

Finalization refuses with `unforked_link_population` when a hand-written membership check
compares a historized link's population as one reading without a fork for that same link.
The source rows and declared history can represent both the current pair per key and every
pair any version related. Put the check in an `ambiguity_group` with at least one other
membership check reading that link, and give each obligation its `reading`, or drop the
hand-written check; the model's generated check reads the accumulated population. Then
finalize again. Nothing is sealed on refusal.

When no `target_model` was proposed, finalization also refuses a spec that scopes tables as
`input` while describing a `same` or `changed` table that the source catalog does not hold,
when the obligations read that table. This indicates a target built from other tables rather
than a one-to-one source copy. The refusal uses `unmapped_reshape`, names the affected tables,
returns `RESULT` with `spec_hash=NONE` and an open question asking the proposer for the
source-to-target mapping, and seals nothing. The seat does not author the mapping; after the
proposer supplies it, retry with `target_model`.

Finalization also refuses when an obligation's source side names a relation with
neither an observation receipt nor one of the documented deferred or carried
bases. On success, the response and `seal.json` include `relations_observed`,
with one entry per relation and its observation basis. This evidence is stored
beside, not inside, the compiled artifact, so it does not change `spec_hash`.

The response and `seal.json` also include `clause_gate`, which reports
`clauses_counted`, `numbered_items`, and `table_rows`. When the commissioned document
has no numbered item or table row, the block includes a `note` stating whether the run
had no document or the document had nothing to count; the absence of a clause is not
reported as silent coverage.

The seal also compares each receipt's `connection` with the source estate named by
the run. If any source relation was observed through another connection, finalization
refuses with `re_anchored`: a landed copy is a different estate, even when its current
contents match. The refusal names the declared and observed connections, the affected
relations, and the observing tool. To accept a substitute deliberately, the operator
must submit `source_estate_basis` on the author-seat run with both `connection_id` and
`reason`; when every foreign receipt matches that declared substitute, the seal proceeds
and records `re_anchored_from` with `declared`, `observed`, and `basis`. Seals that do not
use a substitute carry `declared_source_estate`, `re_anchored_from: null`, and one of
`observed_on_declared_estate`, `declared_source_estate_unrecorded`, or
`no_receipt_to_compare` as `re_anchored_basis`.

The seal also reports an `unlicensed_lineage` review finding when a structural
description/`expected_effect`/rationale or obligation title/rationale says that a source
`NULL` or missing value makes the target value legitimate, acceptable, expected,
or otherwise permitted. A source `NULL` explains a finding; it never licenses
skipping a required invariant. This is a review finding on an otherwise sealable
artifact, not a substitute for adding the required check.

`finalize_spec` applies the relation-name rules to everything the draft holds,
seeded and newly registered alike, before it assembles the artifact. It refuses
when the thread's bound connection changes while it is reading the estate: one
seal describes one estate, and its names, its bind catalog and its provenance all
come from the connection the draft was bound to when the finalize began.

A locus on an `add_table` or `add_derived_mart` item that carries no schema is
qualified with the connection's default schema, receipted on the response as
`requalified_loci`. Loci on other change kinds are left alone: for those, one
segment is a column, not an unqualified relation.

A read that names a relation the spec's own structural items declare created but
carries no schema is then qualified from the declaring item's locus, receipted as
`requalified_reads`. When the declaring item names no schema and the connection
supplies no default, names a schema the bound catalog does not hold, or two
declared relations share the name, the read is refused by name instead of
guessed. A read of a relation the spec does not create is left alone — it names
the frozen source estate, where the connection's own default schema resolves it.

An invariant obligation's bare `relation` field is qualified by the same pass. A relation
declared by this spec resolves to that declaration's locus; otherwise a bare name resolves
against the connection's default schema when that schema is known. Already-qualified names
are unchanged. If more than one declared locus matches, the pass refuses rather than guesses.
The rewrite appears in the finalize response's relation receipts and is included in the
seeded-round diff as a licensed normalization; it does not authorize any other obligation
change.

Both receipt lists ride every finalize response — the seal and every later
rejection alike — and are recorded on the run row's finalize round. A rejection
is not a rollback: the rewrites stand, and the next round starts on the rewritten
draft. Neither list is written as an empty list: absent means the rule found
nothing to rewrite on a round that reached it.

If the connection's schema list cannot be read, the created-relation rules cannot
decide anything, and `finalize_spec` refuses any draft that holds a name they
would have had to decide: a relation-creating locus written with no schema, or a
read with no schema of a relation the spec declares created. The refusal reports
`catalog schemas unavailable for <connection>` and names each such item, and
seals nothing. A draft holding no such name is unaffected and seals normally, so
a transient metadata failure does not block a spec the rules had nothing to say
about. The test is of the draft's contents, not of how it was filled — an
authored locus registered before the run bound a connection has not been through
the registration-time locus rule either.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `spec_name` | string | none | Short name for the sealed spec and its artifact identity. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft to assemble and seal. |
| `user_id` | string | implicit | Recorded as the front-door registration operator. |

Example sequence:

```text theme={null}
load_prior_spec(spec_hash="<the spec_hash the grade or review named>")
list_draft()
register_structural(item_json='{"spec_id":"change-1", ...}')
register_obligation(obligation_json='{"obligation_id":"obl-1", ...}')
register_settlement(settlement_json='{"question":"...", "chosen_reading":"...", "grounded_by_sql":"SELECT COUNT(*) ..."}')
add_lean(obligation_id="obl-1", lean_json='{"reading":"...", "justification":"..."}')
finalize_spec(spec_name="customer-churn-conformance")
```

For a new spec, omit `load_prior_spec` and start with the registration tools.

`finalize_spec` records each attempt on the thread's run history. A rejected
attempt is recorded with its findings, while an interrupted seal is recorded as
`pending` or `failed`; retrying `finalize_spec` for the same artifact completes
that attempt instead of creating a second one. A successful response includes
`sealed: true`, the `spec_hash`, artifact counts, and the published artifact
`path`. If the final history write fails after the seal and front-door
registration succeed, the response still reports the completed seal and tells
you to rerun `finalize_spec` to complete only the history transition.

A successful response can also include `review_findings`. These are advisories:
they do not prevent the seal, and apply under either interpretation policy.
`contradictory_live_clarifications` names live
estate rulings that disagree. Only structured TIME-encoding statements can
disagree: they are compared by relation and column, and the finding names
every live ruling on that column. Prose statements are never read for their
meaning, so they are never called contradictory. Instead,
`overlapping_live_clarifications` names every live ruling on one subject when
there is more than one. It says whether they record the same ruling, without
claiming whether reworded rulings agree. Subjects match when they are equal
(ignoring case and spacing). Reworded subjects match only when they name the
same identifiers and one subject's content words contain the other's. Word
order and filler words do not matter, and a word may be added, but a word is
never replaced: "rounding of orders.amount" matches "orders.amount rounding",
while "timezone of orders.created\_at" and "precision of orders.created\_at" stay
separate, as do "legitimately empty" and "correctly empty". A ruling joins a
group only when it matches every ruling already in it. Retired rulings do not
count. If the register cannot
be read, the finding says the contradiction check was not completed. To resolve
a duplicate or superseded ruling, withdraw it on the owner's word or have a
person overturn it on the review screen. When the run names an estate, this
check reads the clarification store twice.

`uncovered_structural_item` names an `add_table`, `add_derived_mart`, or
`add_column` structural item with `change_expectation: "must_match"` that no
sealed check reads and whose source catalog has no same-named object or column
to compare. The item therefore remains unconfirmed on every build, including a
correct one. Register an obligation that reads the item, or explain in the
thread why it remains unconfirmed. This source-catalog check runs only when
such an uncovered item exists and a source connection is bound; it uses one
metadata round trip per distinct schema and one per relation named by those items.

See the [spec conformance endpoints](/docs/Genesis-API/API-Reference#estate-endpoints) for reading the registered artifact by hash and running downstream grading.

### `author_spec`

Hand a migration ticket to the spec-author seat. The run refuses a sealed spec when
its relation evidence came from a different connection than the requested estate,
unless the operator explicitly declares that the other connection is the source of
truth for this run.

On an unattended mission turn, `author_spec` uses the mission's originator for its
visibility checks on the connections, estate, and any named prior run, even when the
turn has no user context. This lets a goal-mode mission author against resources its
originator can see; it does not change the run's caller or attribution. See [unattended
mission visibility](/docs/Genesis-Prover/Agents-And-The-API#unattended-mission-visibility)
for the identity and permission boundaries.

Before the seat starts, Genesis checks that the configured model provider answers;
an `unavailable` refusal carries the classified `cause` and its remedy instead of
starting a run. The shared probe and its cache window are configured by
[`llm.provider_preflight_ttl_seconds`](/docs/Setup/Advanced-Settings#llm-streaming-timeouts).

See the [Genesis Prover overview](/docs/Genesis-Prover/Overview) for how specification-
authoring model usage appears in Pulse Costs.

If an authoring run later makes no progress for `estate_char.spec_author.no_progress_seconds`,
the seat stops the stalled turn through the owning runtime before returning
`error_type: "run_stalled"`; refused stop requests are retried under
`estate_char.spec_author.stall_stop_attempts` and
`estate_char.spec_author.stall_stop_retry_seconds`. Poll the run after a stall and check its
summary before submitting again, because the summary says whether the runtime accepted the
stop or the retry limit was exhausted. For terminal run-summary fields, see the
[author-seat API reference](/docs/Genesis-API/API-Reference).

A **one-line ticket is a valid brief** — *"Migrate the `SALES` database to the target
system as-is; the data values must match"* — and is the right one for a lift-and-shift. Pass
the user's own words; do not pad the ticket with what the system diff already measures
(object presence, column presence, types, row counts with row identity, value
distributions, keys). Write more into the ticket only where the user states something
the diff cannot see: a business rule, a derivation, a domain, a reshape, an aggregation
or a new mart. The diff only *compares* the two estates, so anything the user states as an
absolute — "exactly 1.2M rows", "this column must be DATE" — belongs in the ticket even
though the diff measures that property relatively. 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 spec delivers a verdict.

Separate the commission from operator background. Pass the business request and requirement
documents as `requirements` (or under the older `ticket_text` name); if both are supplied,
they must contain the same text. Pass build history, reload details, or earlier findings as
`context`, not as requirements. The seat sees context in its own block and records it apart
from the ticket. At sealing, an obligation whose rationale cites only context is refused
with `operator_context_obligation`; context is background, not evidence of a requested
check. A `written_by` obligation is refused with `unrequested_mechanism_obligation` unless
the requirements name its demanded mechanism, such as a job, notebook, or pipeline. Record
build background with `register_substrate` when appropriate.

In a repair round, these checks carry forward independently by `obligation_id`: the context
check does not re-judge an obligation whose rationale is unchanged from the prior seal, and
the mechanism check does not re-judge one whose `kind` and demanded `writer.mechanism` are
unchanged. Other edits, such as rewording the title, do not by themselves make the carried
part a new demand. A changed rationale is checked for context support, and a changed kind
or mechanism no longer meets the mechanism check's carry-forward test; a non-carried
process obligation is checked against the requirements again.

A repair round loads its named prior seal before registration and carries forward the still-
standing clarification rulings already cited or used to answer questions anywhere in that
seal's repair lineage. Caller-supplied `clarification_ids` are still validated against the
named `estate_id`; retired or cross-estate caller ids refuse the submit, while a carried ruling
that is no longer valid is left behind. The run summary records inherited ids in
`clarifications_carried_from_lineage`, separately from caller-named ids. On the brief, the
seat is told the prior seal's ticket and which ticket lines are new, when both ticket texts
were recorded. It is also given earlier rounds' questions and proposed owner-rule checks, so
it does not ask the owner the same question or offer the same check again on an unchanged
fact. Earlier answers superseded by a later resolution are not carried as current rulings.
Every open question and proposed rule must be returned in the same `RESULT` line; withholding
one for a later round would offer it again on reseal. Exact repeated rule offers are retained
in `owner_rule_offers_already_made` in the run summary rather than being presented to the
owner again. A repair may ask or offer again when the ticket or measured estate changes the
fact the earlier question or offer rested on, and must state that change.

For a document attached to the current chat, use its File ID or Git Path as an `upload`.
The attachment notice may also spell its Git Path as a repository asset in `uploads`:
`repository: {bot_git_repo: "uploads", path: "<notice path>"}` is read as that upload
when this instance has no local bot-git repository named `uploads`, and its `ref` may be
omitted. If a local `uploads` repository exists, include its `ref` to read the path from
that repository; omitting the ref is refused. Other repository assets require a `ref`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `requirements` | string | `""` | What the business asked for: the ticket and requirement-document text. Send this or `ticket_text`; at least one must be non-blank. If both are non-blank, they must match. |
| `ticket_text` | string | `""` | Older name for `requirements`; it is the same input. Send this or `requirements`; if both are supplied, they must match. |
| `context` | string | `""` | Optional operator background, such as how the build ran, what was reloaded, or what an earlier run found. Kept apart from requirements and never graded. |
| `interpretation_policy` | string | `""` | Optional; omit it. `lean`, the only policy, commits to the most likely reading and flags the assumption. `open` is retired and refused with `kind: "invalid"`; a spec sealed under `open` is repaired under `lean`. |
| `authoring_tooling` | string | `""` | Optional per-run authoring tool set: `registrar`, or `classic` only to repair a spec sealed with it. Omit or leave empty to use `estate_char.spec_author.authoring_tooling` (default `"registrar"`). `classic` is retired for new specs and requires `repair_of`; without it the call is refused with kind `invalid` and nothing starts. `registrar` adds the Registrar's tools and phases to this run's thread; a fresh round seals from `final_review`, or from any phase once every phase check passes on its draft, while a repair skips the phases. See [`spec_author_registrar_tools`](#spec-author-registrar-tools) for the phase sequence and added verbs. The run and seal record the choice. On a repair, if this field was omitted and `repair_of` names the prior, submit inherits that seal's tooling when its provenance is readable; the handle names the effective tooling from the start and records it as inherited. An explicitly named mismatch is refused at finalization. Other values refuse with kind `invalid` and start nothing. |
| `repair_of` | string | `""` | The `spec_hash` of the seal this run repairs, for a repair of any tooling. When the run names no `source_catalog` / `target_catalog`, the seat reads in that seal's catalogs from its first query rather than only after `load_prior_spec`, and it seeds from that seal alone. A hash no spec is sealed under is refused with kind `invalid` and nothing starts. Required with `authoring_tooling: "classic"`, where it must name a classic seal. |
| `resubmission_of` | string | `""` | Optional `run_id` of the earlier seat run to resubmit, replacing the conversation's round lookup. With `target_model` omitted, carries that run's mapping only if a seat registered it (possibly in an earlier round); `data.target_model_carried_from` names the registering run. A named run with no mapping carries none. An unknown or invisible run and a non-seat run refuse the call; if `target_model` or `repair_of` is supplied, the named run is checked for seat type only. Otherwise, a proposed mapping no seat registered refuses the call. |
| `source_estate_basis` | object or null | `null` | Optional operator declaration with exactly `connection_id` (the substitute estate) and `reason` (why it stands in for the source). Both fields are required when the object is present. |
| `source_catalog` | string | empty | Catalog (database) for source-side reads and source relation columns at the seal. Use it when the source tables are not in the connection's default catalog. On a shared connection with separate source and target catalogs, an ad-hoc seat query uses `target_catalog` when it names at least one schema present only in the target and none present only in the source; schema-like names present in neither catalog (for example, a relation alias) do not affect that choice. A statement naming at least one source-only schema and one target-only schema cannot be answered by one session catalog. On Databricks it runs as one statement with every `schema.relation` spelled `catalog.schema.relation` in the catalog that alone holds its schema, when that is sound: the statement is exactly one query, every relation names its schema (a CTE's own name excepted), and each schema is held by exactly one of the two catalogs. Otherwise, and on any other engine, it is refused before sending, naming both remedies: one read per side, or each relation spelled with its catalog in that ad-hoc read. The tool result then carries the statement that ran as `executed_sql`. On such a run a statement naming any relation without its schema (a CTE's own name excepted) is refused before sending, because a bare name belongs to neither catalog; name its schema. Routing uses the normalized SQL the tool executes, so code fences and routing prefixes do not hide the statement's schemas. Other ad-hoc reads use this source catalog. A catalog on an engine that cannot bind session catalogs is refused before the run starts. |
| `target_catalog` | string | empty | Catalog (database) the seal reads the target side in: target relation columns, the target-engine prepare of every target-side check, and the registration check for an invariant declaring `invariant_side: "target"` when source and target use separate catalogs of this connection. Other registration checks use `source_catalog`. Use it when the target tables are not in the connection's default catalog. With `target_connection_id` it is a catalog of that connection and only the target-engine prepare reads it. A catalog on an engine that cannot bind session catalogs is refused before the run starts. |
| `target_connection_id` | string | empty | The registered connection the target is on; it may equal `connection_id` when both estates use one connection with separate catalogs. Before sealing, the seat prepares every target-side check on that connection's engine, runs each accepted one over at most 1,000 rows of every relation it reads, and refuses a check the engine rejects or fails to run. If neither this field nor `target_estate_id`, `target_catalog`, or `source_catalog` places the target, a commissioned run with target-side checks is refused at seal as `target_not_placed`. An unknown or ambiguous connection is refused `invalid`, and one the authenticated user or relaying agent may not use is refused `permission`; neither starts a run. |
| `target_estate_id` | string | empty | The registered target estate paired with the source (for example, the `target_estate_id` returned by `readiness`). Its registered connection becomes `target_connection_id`. If both target fields are supplied, they must name the same connection. An unregistered estate is refused with `not_found`; an estate with no connection, or one whose connection disagrees with `target_connection_id`, is refused with `invalid`. This adds one primary-key estate read off the event loop before commissioning; the derived connection is screened as `target_connection_id`. |
| `target_column_types` | array of objects or null | `null` | Optional caller assertions for physical target columns. Each object requires string fields `relation`, `column`, `native_type`, `source_clause_ref`, and `provenance`. These are not observed target DDL. Supplying them adds one registry read to identify the commissioned target engine, off the event loop; no target DDL or data is queried. See [target column type assertions](/docs/Genesis-Prover/Overview#target-column-type-assertions) for how the authoring run handles them. |
| `target_type_dispositions` | array of objects or null | `null` | Optional chosen storage for declared, zone-free TIME columns. Each object requires string fields `relation`, `column`, `physical_type`, `encoding_rule`, and `clarification_id`. It must join a declared TIME column; undeclared, duplicate, non-TIME, or time-zone-bearing declarations are rejected. A Databricks or unidentified target requires a person-ratified disposition for each declared TIME column to seal. Currently only `physical_type: "STRING"` and `encoding_rule: "HH:mm:ss"` are accepted. Each disposition reaching ratification validation costs two clarification-store reads at seal. See below for the ratification statement format. |
| `target_model` | object or null | `null` | The proposer's source-to-target mapping for a split, merge, derived target, Data Vault, or Medallion build. It must be one object in the version-2 `target_model` schema, never a list; the seat validates it against the source, registers the mapping and its rendered obligations, and never invents one. |
| `notify` | boolean | `true` | When `true`, notify this tool call's thread with the terminal run result, including any open questions the seat left. Set `false` when you intend to poll with `get_run` yourself. |

When a conversation resubmits the same commission without `repair_of` (same conversation,
source and target connections and catalogs, and `spec_name`), it may omit `target_model` only
if a seat in that commission's last 20 rounds registered the newest mapping previously
proposed; it is carried unchanged under its original `asserted_by`, and
`data.target_model_carried_from` names a round whose seat registered that mapping. `estate_id`
does not split the commission: for a resubmission that names an estate, the pre-check reads
rounds for that estate or for no estate; when the resubmission names no estate, it reads all
rounds in the commission. If no compatible round's seat registered the newest proposal,
submit refuses before starting another seat and asks for the mapping again. With no earlier
proposed mapping, the pre-check leaves the request to the seat. A commission that should carry
no mapping needs its own `spec_name`. An omitted mapping without `repair_of` costs one indexed
run-history read and one batched read of two summary fields for up to 20 rounds; it reads no
estate and makes no model call. See the \[author-seat API reference]
(/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-author-seat) for the HTTP
request and response fields.

The sealed provenance also records which authoring settings the deployment default decided
in `seat_settings_defaulted`; see [run provenance](/docs/Genesis-Prover/How-A-Run-Works#provenance-which-build-which-rules-which-database)
for how to read that field.

Layered Medallion mapping rules are documented in [Declared target mappings and Data Vault
shapes](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes).
`author_spec` returns `layered_source_undeclared` or `unanchored_derived_target` when those
checks fail; neither refusal seals the specification.

For a stalled `author_spec` run, follow `next`; see the [author-seat API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-author-seat).

Send `source_estate_basis` only when the operator has made that declaration in words;
quote the operator's reason. Do not infer it from a ticket, an estate, or an earlier
run. A partial object is refused and no authoring run starts. When the declaration
matches the observed substitute connection, the sealed result records the substitution.

When one connection serves both estates as two catalogs, pass both catalog names so the
seat reads each side in the intended catalog. Omit them when the connection's own catalog
already holds the tables; an omitted side reads that connection catalog. The commissioned
catalogs are kept on the run and used by estate reads, so a same-named relation in a
different catalog is not silently accepted. On a split-catalog run, a declared
`invariant_side: "target"` routes its registration check only to `target_catalog`; other
registration checks use `source_catalog`.

On Snowflake, each named catalog must be a bare identifier or one complete
double-quoted identifier; double quotes inside the quoted name must be doubled. A
catalog name outside those forms is refused before the authoring run starts. This checks
whether the name can be bound safely, not whether the database exists or is accessible.

When the seal reads schema and relation names returned by Snowflake's catalog listing, it
addresses each listed name as stored: mixed-case and lowercase names are double-quoted, so
they are not folded to a different uppercase object. Names not returned by the listing
continue to use the spelling supplied by the artifact. If a listing contains both an
uppercase name and a case-insensitive match, the uppercase name is selected, matching the
object a bare Snowflake identifier reaches.

When `ticket_text` is present, the sealed artifact retains it as
`provenance.instruction_text` and records its byline in
`provenance.instruction_text_submitted_by`. A direct operator call is recorded as
`user:<operator>`; when an agent relays the ticket through this tool, it is recorded as
`agent:<bot_id>`. The byline identifies who submitted the retained prose, while the run's
`operator` remains the authenticated person who invoked the tool. If no ticket text was
submitted, neither field is added.

Pass `clarification_ids` when the seat may rely on decisions the ticket did not settle.
Each id must name a record created by `record_clarification`, and `estate_id` is required
when ids are supplied. An unknown id, an id recorded for another estate, or ids without an
estate refuses the request before a run starts. The seat and the sealed specification carry
the record's label and recorded identity; prose in the ticket is never substituted for the
record. A completed run may also surface a true check declined because the ticket states no
rule requiring it. A numeric maximum or minimum may be labeled an observed bound in
the notice; see [Prover guidance](/docs/Genesis-Prover/Agents-And-The-API#open-questions-and-provider-faults)
for what that means and how to offer the check to the ticket owner.

For `target_type_dispositions`, the referenced clarification must belong to the run's estate
and a signed-in person must ratify it through the [clarification review API](/docs/Genesis-API/API-Reference#clarification-review-and-reopened-verdicts).
Record its statement as the prefix `TARGET TIME ENCODING v1: ` followed by one JSON object
with exactly `relation`, `column`, `physical_type`, and `encoding_rule`; the fields must state
the exact choice for that column. For example, the statement for `EVENTS.START_TIME` is
`TARGET TIME ENCODING v1: {"column": "START_TIME", "encoding_rule": "HH:mm:ss", "physical_type": "STRING", "relation": "EVENTS"}`.
After the person ratifies that clarification, pass its id in the matching disposition:
`{"relation":"EVENTS","column":"START_TIME","physical_type":"STRING","encoding_rule":"HH:mm:ss","clarification_id":"<id>"}`.
The `author_spec` seal validates the current ratification and stores the selected encoding
in the sealed specification. A repair round revalidates a carried encoding against the
current clarification record and drops it if that column is newly declared non-TIME. Do not
invent a disposition or ratification; native TIME storage is not supported by this gate yet,
and `TIMETZ` or `TIME WITH TIME ZONE` cannot use `HH:mm:ss` because it would discard the
offset.

Pass `target_model` when the user describes a target that does not keep the source's tables
one for one — a Data Vault, a Medallion build, any split, merge or derived table. It is the
source-to-target mapping, and the proposer writes it: the seat never does. A mapping that
does not parse refuses the request before a run starts. The seat checks one that parses
against the source (every source column carried or declared dropped, every named column
present, each hub's business key unique and non-null, and each rendered link's full key
identifying one junction row), registers it with the obligations it renders, and otherwise
ends the run unsealed with its findings for the proposer. When a key can be read, the
refusal reports repeated link keys with the source row, distinct-key, and repeated-key counts
and names a dependent child to add; it reports key parts that are `NULL` too. An unavailable
or unsupported source is reported as unmeasured rather than unique. A vault or
Medallion ticket sent without one is returned asking for it; if the resulting spec scopes
inputs and describes a non-source target, finalization returns `unmapped_reshape` and seals
nothing until the proposer supplies the mapping.

Finalization returns `unassessed_but_assessed` when the spec also assesses a table the mapping
leaves unassessed, and `unassessed_without_scope` when the spec declares no scope. The
[Prover mapping guide](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes)
gives the declaration shape and comparison behavior.

Every `input` in the spec must also agree with that mapping before the seat can seal. The
mapping must declare the input as loaded into nothing — a split with an empty `images` list,
or a source of a derived target. If the mapping carries the input into an image, or does not
name it at all, `finalize_spec` refuses the seal with `undeclared_input`; the refusal lists
each offending object and nothing is sealed. The proposer must correct `target_model`, or
remove the `input` scope when the ticket does not describe an input.

Before sealing a spec with a declared `target_model`, `finalize_spec` also prepares each
obligation's `target_sql` against the empty target catalog described by that model. For an
invariant declaring `invariant_side: "target"`, it also prepares the target-side
violation-count statement the grade composes for that invariant. Each relation is checked
against its own declaration: when the SQL names a schema where the model declares that
table, the check uses that schema's declared columns plus any unqualified declaration of
the table; when the SQL names another schema, it uses the union of the table's declarations.
If either statement reads a column or table the model says is absent, the seal is refused
with `unrunnable_on_target_model`; the refusal names the affected obligations and the
missing relations or columns, and nothing is sealed. Rewrite `target_sql` to use only
declared objects — for example, join a link's hash keys to its hubs to reach a business key,
or read the hubs, satellites, and links that receive a split legacy table; a legacy table
that only derived targets are built from (a Medallion gold table's `sources`) is read in
`source_sql`, with the derived target in `target_sql` — then re-register the obligation
under the same `obligation_id` and finalize again. A spec without `target_model` keeps the
prior behavior and does not run this target-catalog check.

`finalize_spec` asks the target engine to prepare, without reading a row, every obligation's
`target_sql` and the check of every invariant declaring `invariant_side: "target"`, and then
runs each statement it accepted with every relation the statement reads capped at 1,000 rows
(each relation replaced by `(SELECT * FROM <relation> LIMIT 1000)`), so an error the engine
raises only while evaluating a row — `INVALID_ARRAY_INDEX` from `array[0]` on an empty
array — is found before the seal rather than on every proof. A run error refuses the seal
with `target_engine_rejected`, quoting the engine; a statement that cannot be bounded that
way, or whose bounded form the engine does not accept, is not run and is listed under
`not_executed`. This adds one live round trip for each accepted statement and one more when
a sampled run errors and its bounded form must be prepared. Only the sampled rows are
evaluated, so a row outside the sample can still raise the error at grade time. When
`target_connection_id` was commissioned, preparation uses that connection and its engine;
otherwise, it uses the seat's connection when a `target_catalog` or `source_catalog` places
the target there. A statement the engine rejects refuses the seal with
`target_engine_rejected`, naming the obligation and quoting the engine's error; rewrite it
in the target's dialect, re-register it under the same `obligation_id` and finalize again.
A statement over a relation the target does not hold yet is not refused, unless a relation
it reads is one the spec declares on the source side (an `input` or `excluded` scope entry,
or a legacy object the `target_model` puts on no target) and the target engine, asked about
that relation alone, does not hold it: the seal is then refused with
`target_reads_source_object`, naming the obligation and the relation. Read a source relation
in `source_sql` only. This adds one live round trip for each such relation. The result — a
refusal included — carries `target_engine_prepare`, whose `status` is `prepared` only when
there are no rejected statements, `rejected` when a statement fails at either `prepare` or
`run`, and `not_prepared` when the target is not placed on a connection or the engine cannot
be reached or refuses this caller access. A seat run commissioned with no target placement
at all (no `target_connection_id`, no `target_catalog` or `source_catalog`) and holding a
target-side statement is refused with `target_not_placed`, naming each statement it could not
send; commission the run again with `target_estate_id`, `target_connection_id` or a catalog.
A thread with no seat run keeps the `not_prepared` record and seals. Its `connection` identifies the selected target
connection. `execution_row_cap` is `1000`; `executed` lists the obligation ids whose sample
runs succeeded, `not_executed` lists checks not run with their reasons, and each entry in
`rejected` includes `stage` (`prepare` or `run`). A `run`-stage rejection means the engine
accepted the statement but raised an error while evaluating sampled rows.

On a spec whose `target_model` declares a placeholder row — a hub's `ghost_keys`, or a
derived target's `unknown_member` (`{"column": …, "values": [...]}`) —
`finalize_spec` refuses with `invariant_over_declared_unknown_member` a target-side
invariant over that relation that puts a constraint the grade counts on any other column (a
`finite`-only rule is never refused), or constrains the member's
declared key with a constraint its declared value breaks, judged as the grade counts it: a
NULL key breaks only `not_null`, and `finite`, which the grade records and never counts,
refuses nothing. The refusal names the obligation, the
relation and the member. It reads those fields only — never the derivation's prose, never a
row of the build; restate
the rule as a `recompute` that excludes the member, re-register it under the same
`obligation_id`, and finalize again.

When `assets` is supplied, the intake and seal also carry `asserted_by`, stamped from the
call's own identity (`agent:<bot_id>` or `user:<operator>`), and a `label` such as
`canonical, asserted by agent Eve`. The asset cannot override that byline.

An asset may carry its document as inline `content` (up to 2 MiB, or `2,097,152` characters),
as `repository` (`bot_git_repo`, `ref`, and `path`), or as `upload` (`file_id`), never more
than one. An upload is a file attached to the current chat; use the File ID or Git Path
shown by its attachment notice. The repository must be a
local Genesis bot-git repository that the submitting operator can read, and an upload uses
the same read grant as the `uploads` repository. Genesis reads the
file at submit, accepts it only when it is whole text within the limit, and refuses the
submit before starting a run when access or reading fails. Asset names must be unique across
label-only and document-carrying entries. The document is stored with the run rather than
copied into the brief, so the seat reads it with `read_spec_asset` before authoring. The
intake and seal retain only its pin: `source`, `chars`, `content_sha256`, and the storage
metadata needed to identify the bytes read.

Before a run starts, the seat counts the numbered items and table rows in the ticket and
its document assets. It refuses the submission when that total is greater than the
capacity of the registration budget: at most `100` clauses per
`register_clause_accounting` call, multiplied by
`estate_char.spec_author.max_registration_calls` (default `200`, bounded `10`..`5000`).
The refusal is returned as validation error `422` and no authoring run is created. This is
an upper bound rather than a guarantee, because other registration calls share the same
budget; a bundle below the clause ceiling can still exhaust it during authoring.

If a pinned document cannot be read when the seat finalizes, the round is refused with
`rule: "asset_documents_unreadable"`. The refusal records whether the asset was missing
or the asset store failed, and does not treat the unreadable document as an empty document
or as an accounting gap.

### `read_spec`

Read a sealed specification by `spec_hash`. Alongside the seal-verified artifact and
authoring provenance, the response includes `who_decided`: the reliance sentence, each
recorded clarification with its label, each declared asset with who asserted its label,
the byline for submitted ticket prose, and—when the specification carries a proposer's
`target_model`—`target_model_asserted_by`, the server-stamped identity that supplied the
mapping. It also returns `offered_not_adopted`: checks the sealing seat offered as stated
rules, and preserve-the-source migration defaults it offered instead of registering, that
the seal does not carry. Each entry has its obligation id, statement, seat run id, and a label
stating that it is not graded. These offers are listed once per obligation id as context, not
added to the specification. A migration-default offer is not an owner question; commission
a repair with `repair_of` for the seat to register it. A seal made before clarification
provenance was recorded reports `clarification provenance unknown`; it is not treated as a
customer's ruling. The tool requires `ratify_source_contract` and does not recompile the
artifact.

<a id="spec-author-registrar-tools" />

## `spec_author_registrar_tools`

The Registrar's authoring tools for a spec-author seat run commissioned with
`authoring_tooling: "registrar"`, the deployment default. A per-run `classic` override is
accepted only when repairing a spec sealed with classic. The seat service adds this group
to that run's thread, alongside the seat's own default groups. It remains through the seal's closing turn and is
withdrawn when the run becomes terminal; a Registrar call after sealing refuses and
withdraws it immediately. It is not in the default tool groups. The classic
`spec_author_tools` group and its behavior are unchanged. The run must use the registrar
tooling recorded at submit; these verbs refuse on a classic run.

### Progressive authoring

A fresh registrar round begins at `scope_population`. The four phases are:

| Phase | Complete the phase by |
| - | - |
| `scope_population` | Register the in-scope objects and, when the proposer supplied one, the `target_model`. `register_model_fields` closes this phase when its check passes. |
| `model_fields` | Register structural items for changed objects and every declared column of derived targets. One `register_model_fields` call can register all derived targets and their declared columns; it closes this phase once its check passes. |
| `obligations` | Register the executable checks; keep unresolved readings as forks. |
| `final_review` | Review coverage, correct earlier registrations in place if needed, then call `finalize_spec`. |

Each closed phase is checkpointed on the run row with a digest, counts, registered ids, and
`closed_by`, which identifies what closed that phase. It is `advance_author_phase` for an
explicit advance, `register_model_fields` when that registration completes `model_fields`,
and `finalize_spec` when sealing closes a phase. When later-phase content is first
registered, the draft at that point is pinned for the phase it moves on from: a structural
item ends `scope_population`, while the first obligation or settlement ends
`scope_population` and `model_fields`. That checkpoint names the first registration that
crossed the boundary as `first_<kind>_registration` (for example,
`first_structural_registration`). If that phase's check passed on the pinned draft,
closing it later—including at `finalize_spec`—records that snapshot, not the later draft.
If it did not pass then, its checkpoint uses the draft as it stands when the phase actually
closes.
The shared classic registration verbs remain available throughout. `register_model_fields`
returns a `phase` block with the current phase, phases closed by that registration, next
instructions, and any outstanding requirements; if a checkpoint cannot be recorded, the
block includes `not_recorded`. When the registered `target_model` declares no derived
target and every changed object already has its structural item, `advance_author_phase`
can skip `model_fields` while closing `scope_population`; its reply lists the skipped phase
and reason. This tool is otherwise mainly for explicitly closing a phase with nothing to
register; `skip_reason` explains why, but never waives required registrations.
`finalize_spec` seals from any phase once every phase check passes on the draft, and the
seal records checkpoints for every phase, including phases not previously closed. Otherwise
it names what is outstanding. Every object registered with
`expectation: "changed"` still needs a structural item before the spec can seal. After the
run ends, these verbs refuse.
Repair rounds seeded by `load_prior_spec` have no phases: correct the seeded draft and
finalize it directly.

### Grouping hints

On a registrar run, a reply from `register_obligation` or `register_obligations` can carry
`grouping_hints`: each names three or more obligations in the draft, at least one of them
just registered, that test one predicate over different tables, and suggests one grouped
obligation over them. The hint is advisory and changes nothing; each per-table check stays
registered. Obligations count as the same predicate only when every verdict-deciding field
matches once the word naming their relation is abstracted (`hub_customer`, `hk_customer` and
`'CORE.customer'` against `hub_account`, `hk_account` and `'CORE.account'`), and each
statement reads a single relation. Fork members, checks rendered from the `target_model`,
and either half of a population-root pair (a key-only root beside the check comparing that
population's values) are never hinted. The hint appears only after a Registrar verb has
confirmed the thread's run, and never on a classic run. To act on one, register the grouped
obligation and remove the per-table ones with `withdraw_obligation`.

### `advance_author_phase`

Explicitly close the current phase and open the next. This is rarely needed: a
`register_model_fields` call closes the phases it completes, and `finalize_spec` seals once
all phase checks pass. Use this when a phase has nothing to register; an incomplete phase
is refused with its missing items, and `final_review` has no later phase. When `model_fields`
has nothing to act on, the reply lists it in `skipped_phases` with a `skipped_reason`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `skip_reason` | string | `""` | Optional reason (at least 20 characters) when the phase has no applicable registrations. It does not waive seal checks. |

Cost: one run lookup, a draft copy and digest, and one run-summary read/write. No estate I/O.

### `reopen_author_phase`

Normally correct earlier registrations in place by re-registering their ids. To explicitly
return to an earlier phase, use this tool; the draft remains, but checkpoints from that
phase onward are removed and the phases must be closed again before finalizing. This is not
available on a repair round.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `phase_id` | string | none | Required earlier phase: `scope_population`, `model_fields`, or `obligations`. It must precede the current phase. |

Cost: one run lookup and one run-summary read/write. No estate I/O.

### `checkpoint_draft`

Read the current phase and all saved checkpoints, including each completed phase's digest,
counts and ids. It does not change the draft and is not available on a repair round. No
caller parameters; Genesis supplies the thread identity.

Cost: one run lookup; no write and no estate I/O.

### `register_model_fields`

Register all derived target relations and their columns as structural items in one call.
Columns must be declared by the registered `target_model`, or named in an exact quote from
the ticket or one of the run's asset documents. `all_model_columns` expands to all columns
declared for that derived target. The call accepts one to 25 models and at most 200 model
and field items together. It closes `scope_population` when that phase's check passes and
closes `model_fields` once its check passes after registration. Its `phase` reply reports
the current phase, completed phases, next instructions, and outstanding requirements. Every
registered model and field declares
`change_expectation=must_differ`: the build target holds it and the source does not, so a
grade confirms it by presence and fails it when the build lacks the relation or column.
Presence is all it confirms; a field's values need an obligation that reads it.

Each registered model that is a derived target with a
declared `grain`, one column or several, also gets a grain check, `G-<target>` (for example
`G-CUSTOMER_SUMMARY`; named by the qualified name, its segments joined by hyphens, such as
`G-MAIN-FCT_ORDERS`, when two derived targets share a name). A call registers the checks of
the targets it names: an exact qualified name selects that target; a name at another depth
selects a target only when its last segment is unique. Each check goes through ordinary
obligation registration and its gates. It is a `self_consistency` obligation whose target
side counts the rows beyond one per key, a NULL key included, and whose expected side is
zero, so it satisfies the seal's grain rule for that relation. A composite grain is keyed by
`DENSE_RANK() OVER (ORDER BY <grain columns>)`, which cannot merge two distinct keys as a
joined string could; a row with a NULL in any grain column counts as a violation. That rank
sorts the target on its grain each time the check runs. The reply's `grain_checks`
names the checks registered, any refused,
and each target that got none and why: no declared grain, a declared unknown member with a
NULL key, or a name that would need quoting (including a reserved word such as `order`). The seat writes those grain checks itself, and the
membership and value checks every derivation needs.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `models_json` | string | none | Required JSON object with a `models` list (1–25 entries). Each entry has `relation` (`schema.relation`), `model_spec_id`, `model_description`, `model_expected_effect`, and `columns` (column-name list, `{ "name": "column", "inputs": [...] }` entries for per-column lineage, or `"all_model_columns"`); optional `model_change_kind` is `add_table` or `add_derived_mart` (default `add_derived_mart`), and `source_quote` grounds columns not declared in the mapping. For derived-build lineage, `model_inputs` is a list of source relations (defaults to the target mapping's declared sources), and a column's `inputs` can name source relations and columns as locus strings or `{ "locus": "schema.relation[.column]", "role": "value\|key\|filter\|join\|rowset" }` objects. Optional `model_reference` (`schema.relation`) identifies the original the output must equal; set `model_change_expectation` to `must_match` for that case (default `must_differ`). The call allows at most 200 models and fields together. |

Example:

```json theme={null}
{
  "models": [{
    "relation": "analytics.customer_summary",
    "model_spec_id": "customer_summary",
    "model_description": "Create the customer summary model.",
    "model_expected_effect": "The derived relation is available to downstream users.",
    "columns": "all_model_columns"
  }]
}
```

Cost: one run lookup and one asset-document read, then structural bulk registration of up to
200 items. When a grain check renders, the call also makes one obligation bulk registration,
which reaches the estate once per check. Closing a phase also reads and writes the run summary.

### `register_value_checks`

In the obligations phase of a fresh Registrar round, register the missing keyed comparisons
for derived outputs that must equal a reference original (`must_match`). Call it after
registering the output's column items and your own checks. It finds every output column item
not already compared with that reference and registers one `membership` check per output,
comparing those columns row by row using the output's `row_identity`. Columns whose reference
types are FLOAT or DOUBLE are grouped in a separate `VALUES-<output>-FLOAT` check with
`relative_tolerance: 1e-09`; all other columns use exact equality. This covers derived and
rendered columns as well as columns named in the ticket. Checks already comparing a column
are not duplicated. If the reference lacks a column, the response reports it in
`excluded`. If a relation, column, or key cannot be rendered, or there is no usable key, the
output appears in `not_rendered` and needs a check written by the author. A name is written
unquoted when every engine the check runs on accepts it so: on Databricks and Snowflake that is
decided by the engine's own reserved words, so `date` is written bare on Databricks. The
fresh-round seal refuses while any required value comparison is missing; it reads each check
in the target engine's dialect and names a check it counts for no column.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `keys_json` | string | `""` | Optional JSON object mapping an output relation to a nonempty list of key columns, for outputs whose scope entry has no `row_identity`; for example, `{"analytics.summary": ["account_id"]}`. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

Cost: one run lookup; one connection-record read and the target placement's run lookup; one
read-only single-row query per reference with a gap; one obligation bulk registration when
checks render (the estate once per check); and one run-summary write.

### `profile_source_relations`

Answer a question about what the source holds — a column's type, its NULL and empty-string
counts, how many distinct values it takes, which columns identify every row — by measuring it
instead of asking the owner. For each relation it reads the columns and their engine types without reading a row, then
runs one aggregate query over the whole relation: the row count and, per
column, the NULL count, the empty-string count for text columns, and the distinct count. The
profile also lists `unique_identifiers`, the columns with no NULL and as many distinct values
as rows (a measurement, cited as `data_probe`). Each profile is kept on the run, so asking about
the same relation again costs no query. A relation whose name or a column name would need
quoting, or that cannot be read, is returned in `refused` with the reason.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `relations_json` | string | required | JSON list of schema-qualified source relations, for example `["sales.orders", "sales.customers"]`. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

Returns `profiles`, `measured`, `reused`, and `refused`.

Cost: one run lookup; for each relation not yet profiled, one schema read that returns no
rows (plus one single-row read, in the engine's own syntax, when it reports no column
metadata) and one aggregate query over the whole relation (one connection-record read and
door per call); one run-summary write when anything was measured.

### `register_platform_checks`

In the obligations phase, read and account for rules declared by the run's supplied platform
documents and, for referenced schemas, the SQL catalog. Supported document declarations
include Foundry Pipeline Builder expectations and dbt manifest tests; catalog constraints
include `PRIMARY KEY`, `UNIQUE`, `FOREIGN KEY`, and `CHECK`. It registers a cited check only
when the spec orders the relation and neither the system diff nor an existing obligation
already covers the rule. A relation scoped `same` is covered by the diff. Read the response's
`accounting` for each declaration's status: `registered`, `diff_covered`, `covered`,
`declined`, `not_applicable`, `unrenderable`, or `to_register` (registration was refused).
Write an unrenderable rule yourself with a `requirement_source` citing its declaration, or
raise it as an open question. Catalog disclosures identify rules that could not be read;
the seal refuses when those rules are unknown rather than treating them as absent.

Only an owner's clarification supplied to the run can decline a declaration. Pass its
declaration id and ruling id in `declined_json`; the tool rejects ids or rulings not among
those read by the run. For example:

```json theme={null}
[{"declaration_id": "dbt:test.my_test", "ruling_id": "clarification-123"}]
```

| Parameter | Type | Default | Description |
| - | - | - | - |
| `declined_json` | string | `""` | Optional JSON list (or one object) of `{ "declaration_id": "...", "ruling_id": "..." }` entries for declared rules the owner declined. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Draft key for the active thread. |
| `user_id` | string | implicit | Derived from the requesting user context. |

Cost: one run lookup and one asset-document read; for referenced schemas, two read-only
catalog queries; one obligation bulk registration when checks render (the estate once per
check); and one run-summary write. Catalog constraints are read on PostgreSQL and Databricks
connections; other engines disclose that constraints were not read.

### `correct_rejected_obligation`

Correct fields of obligations rejected by `register_obligation` or
`register_obligations`, without resending whole bodies. The obligation id and `kind` cannot
change, and each corrected body goes through the normal registration checks again. A list
of corrections is applied in one call, each on its own: the reply names `accepted_ids` and,
for each refused correction, its `rejected` entry, so only those need resending. A list
that corrects one obligation twice is refused whole. The call counts once against the
registration budget.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `corrections_json` | string | none | Required JSON object `{ "obligation_id": "...", "set": { "/json/pointer": new_value } }`, or a JSON list of such objects. Each pointer replaces a field or existing list entry. |
| `connection_id` | string | `""` | Optional named source connection for revalidation; empty reuses the thread's bound connection. |

Rejected bodies are held in process memory from the first Registrar verb until the seat run
ends. Ending without sealing also releases the run's saved rejected bodies and population
choice attempts; register the whole obligation again in a new run. If the body was rejected
before a Registrar verb or the process restarted, register the whole obligation again.
Cost: per correction, the estate resolution check and grain probe for one ordinary `register_obligation` call.

### `withdraw_obligation`

Remove obligations from the draft before the seal, for example the per-table checks a
grouped obligation now replaces. To correct an obligation instead, register it again under
the same id. On a repair round, a carried obligation can be withdrawn only by supplying the
`ruling_id` of an owner clarification that this run was commissioned with and that removes
the check. This records the ruling with the withdrawal and allows the seal to record that
obligation's deletion; every other carried id stays. Leave `ruling_id` empty when
withdrawing obligations registered in this round. The call withdraws every named
obligation or none: it refuses when an id is not in the thread's draft, was rendered from
the `target_model`, a carried id has no valid ruling, or the round has sealed. Each
withdrawal is recorded on the run row under `registrar_withdrawn_obligations`, with its
reason, phase, time, and (for a ruled carried obligation) the licensing `ruling_id`. The
terminal run summary retains these withdrawals along with the Registrar phase checkpoints.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `obligation_ids_json` | string | none | Required JSON list of obligation ids exactly as registered, or one bare id; a single JSON string is also read as a one-id list. |
| `reason` | string | none | Required reason, at least 20 characters, recorded on the run with each withdrawn id. |
| `ruling_id` | string | `""` | On a repair round, the id of an owner clarification included in this run that removes a carried check; required to withdraw a carried obligation. Leave empty for obligations registered in this round. Recorded with each licensed withdrawal. |

Cost: one run lookup, one in-memory draft copy, and one run-summary read/write. No estate I/O.

<a id="prover-tools" />

## `prover_tools`

The Prover's action verbs — one tool per act, rather than one per API route. Assign
this group to an agent that should verify spec-driven data work end to end: register the
two estates, scan each side, prove the data work, read the findings back, and hand the
result to a person. This covers migrations and builds checked against a written
definition. It is **not** always-on.

Every verb answers in one of three shapes: a **run handle** for anything that starts
work (a run id, a status, and the run envelope with a link to poll), a **read** for
anything that only reads, and a **refusal** carrying a reason a caller can act on —
whether the agent lacked a permission, named something that does not exist, hit a
conflicting request, sent bad arguments, or asked for something only a named human may
do. Long work is asynchronous: the agent gets a handle immediately and polls it,
optionally asking the server to wait a bounded number of seconds first.

Every answer from `prover_tools` opens with the top-level fields `audience: "agent"`
and `audience_note: "This is for you, the agent: use it to fix your work. Decide what,
if anything, the person needs, and say it in their terms."` This applies to run handles,
reads, refusals and tool faults. The answer is working guidance for the calling agent,
not a message to pass through to a person; the agent decides what the person needs and
relays it in their terms. The legacy `migration_prover_tools` group uses the same marker.

When a Prover run finishes, the agent reports its result. If it succeeded as part of
work the person already asked for or approved in the conversation, the agent continues
with the next step they approved without asking again, unless the person has since said
otherwise. This does not authorize unapproved work or decisions reserved for the person;
the agent asks when it is unsure a step is covered.

Each verb refuses an argument it does not offer by name instead of silently dropping
it. The refusal names the rejected fields and says that nothing was run; check the
verb's parameter table before retrying. Runtime context fields injected by Genesis are
not caller arguments and remain handled internally.

When a turn has no person identity, its own authority covers `author_spec`,
`register_spec`, `read_spec`, `grade`, `adjudicate`, and `consult` when they require
`ratify_source_contract`; it also covers `cancel_run`. Under `view_connections`, an
unattended turn may run the proof loop with `readiness`, `register_estate`,
`characterize`, `prove`, `get_run`, and `read_comparison`, and call the read-only verbs
`list_runs`, `find_proofs`, `list_snapshots`, `read_snapshot`,
`read_correspondence_rule`, `list_clarifications`, `read_proposal`, `read_bundles`, and
`list_packages`. This lets the agent prepare both estates, submit and follow the
comparison, read its verdict, look up prior runs, proofs, scans, correspondence rules,
clarifications, proposals, bundles, and packages without granting the wider
`view_connections` permission to other acts such as `read_finding`,
`record_review_decision`, or `update_estate`. `compare` is not included: `prove` without
a `spec_hash` performs the same comparison. `readiness` still refuses when an answer
requires a person. These reads use the turn's existing visibility: the thread owner's
for a product-woken turn, the verified mission originator's in an unattended mission,
and no person's visibility otherwise; `read_snapshot` uses the turn's own id, which is
narrower still. This changes visibility only, not permission or approval authority; see
[unattended mission visibility](/docs/Genesis-Prover/Agents-And-The-API#unattended-mission-visibility)
for behavior when the originator is absent or cannot be read.
`cancel_run` remains limited to a run commissioned by the current conversation: both the
caller's thread and the run's recorded thread must be present and match, or cancellation
refuses with `not_found`. That scope check costs one additional indexed run read. A turn
carrying a person is not bounded to one conversation; the ordinary permission check
applies. The exception does not extend to `record_clarification` or `certify_substrate`,
which record what a person said and remain refused without a person.

**All three shapes carry `next`** — `{verb, args, why}`, the literal call to make, not
advice. A run handle's is its run envelope's, read back rather than re-derived; a read's
names the verb that consumes what it just produced; a refusal's names the act that unblocks
it, and carries `verb: null` on the kinds no call from this turn unblocks (a permission the
identified person does not hold, a product-started turn with no signed-in person for an act
outside the authority exception above, an id that names nothing, an act only a person may
perform). See [Prover refusal guidance](/docs/Genesis-Prover/Agents-And-The-API)
for the distinction between a permission denial and an unidentified turn. `why` is always
populated, so an agent can judge the suggestion rather than obey it.

Service errors classified by the HTTP layer as unavailable, including
`NotAvailableHereError` and a service that is still starting, return
`refusal.kind: "unavailable"` rather than `"fault"`. When the service is
starting, retry in a few seconds; otherwise, use the refusal's reason and
`next` guidance.

A permanently missing resource is a `not_found` refusal, not a retryable
service fault. This includes a dataset snapshot that was lost and has no
durable copy; refresh the dataset before trying the read again.

The four comparison verbs — `prove`, `compare`, `get_run` for a comparison-bearing run,
and `read_comparison` — also carry a top-level `presented` block. The chat renders that
block as one comparison card; it is `null` on every other answer and never belongs inside
`data`. A running card has no verdict, while a completed card carries the comparison
counts and the change since the previous comparison of the same pair. If an unexplained
shrink became partly undetermined, the change line says `not measured this time` rather
than claiming fewer unexplained; see [Comparison cards in
chat](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat) for the exact
breakdown. When a prior comparison exists, `presented.previous.thread_id` names the
conversation that produced it and `presented.previous.same_conversation` is `true`,
`false`, or `null` when either conversation is unknown; see the same card guidance for
how the chat presents that context. When the card is present, keep the reply brief and do
not repeat its counts;
the [Chat and threads guide](/docs/User-Guide/Chat-And-Threads#review-agent-generated-comparisons-in-chat)
covers what people see.

When a completed card includes an assumptions disclosure, its after-assumptions count
and assumption list are carried in the `presented.verdict` block; the chat renders the
count with an asterisk when the list is non-empty. See [Comparison cards in
chat](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat) for the fields
and interaction. A missing target key declaration may be included in that assumption
list only when the target does not enforce declared keys and the Prover has checked the
key's uniqueness; otherwise it remains an unlicensed finding. See [the Prover comparison
guidance](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff) for the evidence
rules.

For `refusal.kind: "fault"`, follow `next` as a non-terminal re-read rather than a retry;
see [How agents drive the Prover](/docs/Genesis-Prover/Agents-And-The-API#a-fault-is-a-re-read-not-a-terminal-answer)
for the recovery rule.

Every long verb follows that rule now, `grade` included: it claims the round, starts the
grade and hands back the handle. The synchronous whole-grade form is still what
`POST /estate/spec-conformance/grade-compiled` serves, for an HTTP caller that wants the
verdict in the response.

Prover reads and actions use the identity behind the tool call. See [Prover result
visibility](/docs/Genesis-API/API-Reference#prover-result-visibility) for the subject
checks shared with REST, including run adjudication, finding consultation, episodes, and
estate ruling and court records.

Verbs that screen a named estate, snapshot, comparison, run, or connection apply that
person's visibility before reading or starting work. An item they cannot see is handled
like an unknown estate, snapshot, comparison, or run, or an unregistered connection;
the tool does not identify it as hidden. If a connection-grant check is unavailable, the
verb returns `unavailable` rather than claiming the connection is unreadable.

`characterize` and `find_proofs` expose this hint in `data.workflow_skill`; see
the [data-work proving skill guide](/docs/Genesis-Prover/Overview#the-data-work-proving-skill).

**Approval decisions rest on a person.** With authentication enabled, an agent can decide
a Prover Action Review request for the person in the conversation, or for the originator of
the goal, Blueprint, or mission it is carrying out, when the person asked or delegated that work.
`decide_approval_request` records the agent, person, and stated basis. It only decides
Prover requests; other Action Review requests remain for a person to decide. The
`record_review_decision` tool records a comparison verdict on the same basis.
`request_evidence` and `request_test_case_approval` ask for review; see their entries below
for how they behave when authentication is disabled.

| Verb | What it does |
| - | - |
| `register_estate` | Name a database estate so the Prover can work with it. Scans nothing; checks every member connection is reachable. Registering the same scope again returns the existing estate instead of creating a duplicate. Optional git code assets can be attached for later transform analysis. |
| `update_estate` | Edit an estate's definition, including its name, status, scope, members, or attached git code assets. An edit that moves it onto the exact scope of another live operator-registered estate is refused and changes nothing; edits that leave its scope unchanged are allowed. |
| `clone_code_assets` | Clone the git code assets attached to an estate and capture the revision of its Databricks notebooks and jobs, skipping existing ones unless `force=true`. |
| `derive_code_lineage` | Parse cloned code assets and derive transform lineage, skipping existing lineage unless `force=true`. |
| `reproduce_artifact` | Run one declared SQL artifact in a utility estate and compare its output with a live relation; returns whether the artifact reproduces, does not reproduce, or could not be measured. |
| `characterize` | Scan one estate and record what it contains right now. Scan the migration target with `role="target"`. |
| `prove` | The one call that runs the Prover: compare the two scans, and — when a sealed specification is supplied — also grade that specification against the comparison. A platform-only envelope is labelled **No specification attached yet**; it is not a failed grade and does not open a Human Review worklist. See [how the Prover reports measured and specified results](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff). |
| `compare` | The same run without a specification: the structural differences alone. |
| `grade` | Re-grade a new sealed specification against a comparison that already exists, without re-characterizing either estate. Its obligation checks do query both live databases at grade time, so the run reports when each half read. A derived column with no source namesake is confirmed when every sealed check for it passes; a grade whose checks measured nothing is not selected as the displayed chapter. `spec_hashes` grades a SET of sealed specs (a table specified in parts) as one result — one grade over the union of their checks — and, when the structural tier was graded, the finished run's `summary.spec_set_reading` states its members with their seals, overlaps, conflicts and what no spec covers in the review card's words. What a repair round uses. |
| `get_run` | Read how any Prover run is doing. One poll for every kind of run. |
| `list_snapshots` | Resolve an estate id to its scan timeline so you can find the snapshot id required by `prove` or `compare`. |
| `read_snapshot` | Read what one snapshot measured: each object and the row count the scan took, without loading the characterization document. |
| `find_proofs` | Find existing proofs for an estate pair by the names a sponsor uses, and report the proof of record plus the standing review decision. |
| `list_runs` | List recent Prover runs, newest first, to discover what has already been started or completed. |
| `read_comparison` | Read a finished comparison back, always including its folded review state, and optionally including its findings and clustered families. |
| `readiness` | Record or resume the migration readiness checklist for an estate pair, and return what remains open. |
| `read_finding` | Read one finding in depth: its history, the reconciliation episodes it belongs to, or the rows that evidence it. |
| `record_clarification` | Record an agent-made decision a ticket left open so a sealed specification can rely on it with machine-set provenance. |
| `list_clarifications` | List an estate's recorded rulings, their provenance and review state, and the sealed specifications that cite them. |
| `withdraw_clarification` | Withdraw an agent-recorded ruling on the owner's word so new specifications cannot rely on it and relying seals read reopened. |
| `withdraw_assumption` | Stop the Prover relying on one of its default assumptions for a comparison's estate pair; the next comparison reports what it covered as findings. |
| `restore_assumption` | Let the Prover rely again on an assumption an agent withdrew for the estate pair. A person's withdrawal only a person may restore. |
| `export_comparison` | Package a finished comparison and the rows needed to render its card so another Genesis server can read the same result. |
| `import_comparison` | Load an exported comparison bundle onto this server without re-characterizing the estates or re-deciding the review. |
| `author_spec` | Hand a migration ticket to the spec-author seat, which reads it and seals a specification. |
| `read_spec` | Read a sealed specification back by its hash, seal verified. |
| `register_spec` | Register a specification that was sealed outside Genesis so it can be graded here. Supply exactly one of the parsed `artifact`, its exact sealed-file text as `artifact_text`, or an uploaded sealed file as `file_ref`; prefer `file_ref` when the artifact was uploaded. The direct tool-call transport refuses `artifact_text` over 50,000 characters before it reaches the server; use `file_ref` for larger files. |
| `declare_migration_shape` | Declare which way a sealed specification's structural items are supposed to come out — `must_differ` (a change specification: the target must differ from the source) or `must_match` (a lift-and-shift: the target must contain each locus unchanged). Re-seals deterministically with no model, returning a new child `spec_hash` to grade with. Call it when a grade reports structural items `indeterminate` because the migration shape is undeclared. |
| `adjudicate` | Open (or re-read) the adjudicator's proceeding over a grading run's findings. |
| `consult` | Ask for a ruling when a specification's wording genuinely supports two readings. |
| `propose` | Propose how a comparison's findings should be dispositioned, and hand the reviewer a link. Binds nothing. |
| `disposition_system_diff_finding` | Send one system-diff finding back to be fixed by recording `target_defect`; no approval is needed, and the finding stays open until a fresh comparison shows the fix. |
| `read_proposal` | Read a proposal back and see whether it has been decided. |
| `read_bundles` | List the bundles waiting for a comparison's sign-off, or read one bundle and its members. |
| `list_packages` | List every disposition package for a comparison and report how many remain open. |
| `record_review_decision` | Record a run-level review verdict for a person in the conversation or the originator of their goal, Blueprint, or mission, with its approval basis. |
| `decide_approval_request` | Approve or reject a Prover Action Review request for a person, recording the agent and the basis for acting on their behalf. |
| `request_evidence` | Ask for the facts behind one finding before anyone decides it, changing neither estate. With authentication disabled, files the same evidence request the Human Review finding pane's former **Request the evidence** button filed. With authentication enabled, proposes the request in Action Review for approval; a person or an agent using `decide_approval_request` may decide it. Needs `ratify_source_contract`. |
| `request_test_case_approval` | Ask for approval of the current test cases for one view in Action Review. Each request covers whole test cases; a view is approved only when every request is approved. Asking needs `view_connections` and a signed-in person; any signed-in person with `view_connections` can approve in Action Review, and an agent may use `decide_approval_request` for that person. With authentication disabled, records them as approved without human review. |

### `readiness`

Call this before choosing a migration recipe and again when the person answers checklist
items. A call with no answers, spec hashes, or spec assets resumes the current record for
the pair without writing; if there is no record, it returns the open items. Supplying
answers, spec hashes, or spec assets records a revision. The result recomputes facts held
elsewhere and returns each checklist item as `answered`, `derived`, or `missing`.

| Parameter | Type | Default | Required | Description |
| - | - | - | - | - |
| `source_estate_id` | string | `""` | Yes | Registered source estate. |
| `target_estate_id` | string | `""` | Yes | Registered target estate. |
| `answers` | object or null | `null` | No | Checklist answers keyed by item id. |
| `spec_hashes` | string\[] or null | `null` | No | Sealed specification hashes for this pair. |
| `spec_assets` | object\[] or null | `null` | No | Documents and their declared provenance labels. |
| `include_other_conversations` | boolean | `false` | No | Set `true` only when the person in this conversation asks you to use the pair's record from another conversation. |

Genesis injects `bot_id`, `thread_id`, and `user_id`; they are not caller parameters.
The tool records the injected `thread_id` with a new record. By default, when the pair's
record was first recorded in another conversation, the tool withholds its answers and
documents: the checklist is returned as if nothing were recorded, `readiness_id` is
`null`, `answers_withheld` is `true`, and `other_conversation_record` identifies the
record, conversation, and recording time. `recorded_in_thread` and
`conversation_note` explain the mismatch. Only set `include_other_conversations=true`
when the person here asks you to use that record; then confirm each answer with them
before relying on or repeating it. Identical answers submitted from another conversation
keep the first record's conversation provenance.

When `spec_hashes` is empty, readiness reads the pair's latest proof once and can derive
the migration shape from its `change_expectation`. It does not fall back to an older proof
that the latest one did not repeat, and a named sealed spec remains the source of shape
when `spec_hashes` is supplied.

For example, start the checklist for a pair with:

```text theme={null}
readiness(source_estate_id="source", target_estate_id="target")
```

### `record_clarification`

Record a decision the ticket left open so a later specification can rely on it without
mistaking the agent's conclusion for the customer's words. `estate_id`, `subject`, and
`statement` are required strings. The tool assigns the record's provenance from the
runtime identity; there is no argument for choosing or upgrading who decided it. In this
revision, every record is `recorded_by_kind: "agent"` and its label is
`agent-certified (agent <bot_id>)` (or the runtime's unnamed-agent identity when no bot id
is available). A heading in `ticket_text`, including one that says “ratified by the
customer,” is not a provenance record.

The response includes `clarification_id`, `estate_id`, `subject`, `statement`,
`recorded_by_kind`, `recorded_by`, `conversation_with`, `label`, and
`package_item_citation`. That citation gives the `clarification_id` to put on a
disposition package item and states which items it can carry: a `target_defect` or
`spec_defect` over an Adjudicator `question` or `spec_ambiguity`, only when this
clarification is on an estate of the comparison's pair, was recorded after the seat
asked, and was ratified by a signed-in person. Otherwise the citation carries no item;
`propose_finding_disposition_package` refuses the package rather than treating a note as
a citation. Its fields are `package_item_citation.clarification_id` and
`package_item_citation.carries`. Every response also carries `already_recorded`: a
call that repeats a ruling the same agent recorded on the estate, in a conversation with
the same person, that still stands — the same subject as the seal groups subjects and the
same statement up to case and spacing, or for a structured TIME statement the same
column, type and encoding — writes nothing and returns that standing record with
`already_recorded: true` and a `message` naming its id and label. For an agent record,
`conversation_with` identifies the signed-in person by email when available, otherwise by
display name; if neither can be resolved, it is `unnamed` and the label says that the
signed-in person's name is not on record. An email identity can itself name the person when
no user record is available. With authentication disabled it is `unauthenticated`, and it
is absent when the turn had no person. That name does not make the ruling person-ratified:
the record remains agent-certified until a person reviews it. Pass the returned
`clarification_id` in
`author_spec`'s `clarification_ids`; the seat validates that every id belongs to the same
`estate_id` before starting. A signed-in person can later ratify or overturn the recorded
clarification through the Estate API; that review happens after reliance, never as a gate.
Ratification changes the label to `person-ratified` and names the reviewer. An overturned
clarification cannot be supplied to a new `author_spec`, and any seal or run that relies on
it reads reopened. If the owner later takes back or replaces the decision, the recording
agent can withdraw it with `withdraw_clarification`. The tool requires `ratify_source_contract`; when authentication is on
and the turn has a non-placeholder user id, it performs one user read, in addition to one
estate read, one read of the estate's clarifications and one of their reviews, and, when
the ruling is new, one insert and one read. See the [clarification review endpoints](/docs/Genesis-API/API-Reference#clarification-review-and-reopened-verdicts)
for the review request and response fields.

### `list_clarifications`

List the rulings recorded for a registered estate when you need a clarification id or want
to inspect who decided each ruling and where it is used. The response is ordered oldest
first and includes `estate_id` plus `clarifications`; each entry carries its
`clarification_id`, `subject`, `statement`, `status`, `label`, `reviewed_by`, `cited_by`
(the sealed specification hashes that cite it), and `reopened` after an overturn or
withdrawal. Status `withdrawn` means the recording agent retired it on the owner's word;
like `overturned`, it cannot be cited by new specifications. An empty list means the estate
has no recorded rulings. The tool requires `view_connections`, performs no model call or run,
and refuses an estate that does not exist or is not visible with `not_found`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `estate_id` | string | none | Registered estate whose clarifications to list. Required. |

### `withdraw_clarification`

Withdraw an agent-certified clarification you recorded when the owner takes the decision
back or replaces it. Record the replacement first, then withdraw the old clarification and
include the replacement's id in `reason`. Only the agent that recorded the clarification
can withdraw it, and only while it remains unreviewed. A person-ratified clarification is
the person's decision and must be overturned by that person through the review screen;
another agent's clarification is not yours to withdraw. An already overturned or withdrawn
clarification cannot be withdrawn again. The withdrawal is final.

The withdrawal records the owner's words in `reason`. A completed withdrawal prevents the
clarification from being cited by new authoring, question resolution, or proposals. Sealed
specifications that cited it and runs measured against those seals read reopened. The
completed response returns the clarification with status `withdrawn`, `reviewed_by` set to
`agent:<bot>`, and `reopened` with the dependent snapshot captured just before withdrawal.
Its label says `withdrawn by agent <bot> on the owner's word: <reason> (recorded by agent <bot>)`. It requires `ratify_source_contract` and acts with the calling user's estate
visibility.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `clarification_id` | string | none | Required id returned by `record_clarification` or listed by `list_clarifications`; it must be your unreviewed record. |
| `reason` | string | none | Required plain-language account of the owner's words, including the replacement `clarification_id` when there is one. Stored on the withdrawal and shown in its label. |
| `confirm` | boolean | `false` | Set `true` only after the owner has reviewed the preview and agreed to reopen its listed specs and runs. |
| `confirmation_token` | string | `""` | Token from the preview's `data.confirmation_token`; required with `confirm=true` when the withdrawal would reopen dependents. |

If the clarification has dependents, the first call records nothing and returns
`data.confirmation_required: true`, `data.withdrawn: false`, `data.would_reopen`, and
`data.confirmation_token`. Show the owner which sealed specs and runs would reopen and ask
whether to proceed. Only after their yes, call again with `confirm=true` and that token. If
the token does not match the current dependent set, the call records nothing and returns a
fresh preview with a new token. A withdrawal with no dependents proceeds without confirmation.

```text theme={null}
withdraw_clarification(clarification_id="cl_123", reason="The owner replaced this with cl_456")
withdraw_clarification(clarification_id="cl_123", reason="The owner replaced this with cl_456", confirm=true, confirmation_token="<preview token>")
```

The tool performs a clarification estate lookup and record read, one estate visibility check,
one review read, one compiled-spec provenance scan, and one run read for dependents. A preview
does not insert a review event; a confirmed withdrawal inserts one. It makes no model call
and starts no run.

### `resolve_open_question`

Resolve one question that a completed `author_spec` seat could not settle by measuring the
estate. The run-finished notification and `read_spec` list these questions in number order;
resolve each one before using the sealed spec for `prove`. This tool records either an answer
or an explicit decision to continue without one, and a later resolution of the same question
supersedes the earlier append-only record.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `prover_run_id` | string | none | Required `author_spec` seat run id from the returned handle or terminal notification. |
| `question_number` | integer | none | Required question number, starting at `1` in the order the seat reported them. |
| `clarification_id` | string | empty | The answer: a clarification id returned by `record_clarification`. Give this or `proceed_reason`, never both. |
| `proceed_reason` | string | empty | Why to continue without an answer, such as `a benchmark: nobody is available to rule`. Give this or `clarification_id`, never both. |

The response returns every question with `status` (`open`, `answered`, or `proceeded`), its
current label and resolution metadata, plus `open_count`, `next_open_question`, and the run's
`spec_hash`. `owner_answered` is `false` while a question is open or was closed without an
answer; it is `null` when an agent supplied a clarification. Both resolutions are recorded as
the agent's act: a clarification is agent-certified, not the owner's answer unless a person
ratifies it, and proceeding without an answer explicitly says the owner has not answered.
Check the clarification's review for ratification. If someone else must decide, leave the
question open and report it rather than closing it. The tool requires
`ratify_source_contract`; it makes no model call and costs one run read, a clarification/review
read when an answer is supplied, one insert, and one resolution read. It refuses a non-seat or
authoring run, an unknown question number, both or neither disposition, or a missing,
overturned, or withdrawn clarification.

### `withdraw_assumption`

Stop the Prover relying on one of its default assumptions for a comparison's estate pair.
`diff_hash` and `assumption_id` are required; `reason` is optional. The id is one that
`read_comparison` lists in `comparison.assumptions`, such as a proven pair's type
spellings. The withdrawal applies to every later comparison of the same estate pair: the
next one reports the differences the assumption covered as findings, and its summary lists
the withdrawal under `withdrawn_assumptions`. Stored comparisons keep their verdicts; an
approval of a comparison whose pass relied on the assumption reads reopened until the
assumption is restored.
Later proofs and comparisons keep the withdrawal ids and their bylines from the same
snapshot used to key the run; see the [Prover comparison guide](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff).

The act is recorded as the agent's, under the bot id the runtime supplies. The target
platform's identifier-case license (`identifier_case:<platform>`) and the engine's
collation-ordering license (`collation_ordering:<component_pair>`) can also be withdrawn,
but only when the comparison relied on them. Withdrawing the former makes names that
previously matched by the platform fold read as missing and surplus; withdrawing the latter
makes text minimums and maximums abstain rather than compare as content. The tool requires
`view_connections` and performs one comparison, snapshot, run-summary, and withdrawal-log
read, one read of the pair's comparison run ids followed by three projected summary fields
for those runs, and one insert. A person withdraws through
`POST /api/estate/system-diffs/{diff_hash}/assumptions/{assumption_id}/withdraw`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Required full comparison hash from `read_comparison`; the withdrawal is stored for that comparison's estate pair. |
| `assumption_id` | string | none | Required id from `comparison.assumptions`, such as `type_spelling:bigquery->databricks`, `identifier_case:snowflake`, or `collation_ordering:sqlite->snowflake`. The pair's available ids are returned when the id is refused. |
| `reason` | string | empty | Optional plain-language reason recorded on the event and shown with the withdrawal. |

The tool returns the withdrawal event and refuses a second withdrawal of the same assumption
for the pair. If a concurrent change moves the standing while the withdrawal is being written,
the tool refuses instead of appending; read the assumption's standing again before acting. See
the [Estate API response contract](/docs/Genesis-API/API-Reference#post-api-estate-system-diffs-diff-hash-assumptions-assumption-id-withdraw).

### `restore_assumption`

Let the Prover rely again on an assumption withdrawn for the estate pair. An agent may
restore only a withdrawal an agent made; a person's withdrawal is refused as a conflict
and must be restored by a person through
`POST /api/estate/system-diffs/{diff_hash}/assumptions/{assumption_id}/restore`. The tool
requires `ratify_source_contract` and performs one comparison read, one snapshot read,
one withdrawal-log read, and one insert.

It accepts the same `diff_hash`, `assumption_id`, and optional `reason` parameters. A restore
makes the assumption available to the next comparison. If a concurrent change moves the
standing while the restore is being written, the tool refuses instead of appending; read the
assumption's standing again before acting. See the [Estate API restore contract](/docs/Genesis-API/API-Reference#post-api-estate-system-diffs-diff-hash-assumptions-assumption-id-restore).

### `export_comparison`

Package a finished comparison for transfer to another Genesis server. The bundle keeps
the comparison's `diff_hash`, run ids, snapshots, measured objects, estates, review
events, findings, and ratified rules, so the receiving server can show the same card
without access to either database or its credentials. Connection values travel as
references only; credential-shaped fields in stored JSON are redacted. Use
`read_comparison` when you only need to check whether a comparison exists.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Required content hash from a finished proof's `envelope.summary.diff_hash`. |

The response contains `data.bundle`, including an `envelope` with the bundle type,
schema version, contract, export time, source-server identity, connection references,
and estate ids, plus the portable store rows. An unknown hash returns `success: false`
with `type: "not_found"`. Exporting is an expensive read: about two dozen indexed
store reads and JSON decoding for the bundle's payloads.

### `import_comparison`

Load the document returned by `export_comparison` onto this server. The imported card
retains its content-addressed identity; use the returned `estate_id_map` when a source
link names an estate id that differs on this server.

Run `dry_run=true` first when the target may already contain part of the comparison. The
plan reports per-table creates and conflicts, estate adoptions, and referenced
connections without writing. A missing connection is reported but does not prevent the
card from being read; only a re-run or live replay needs that connection.
If a correspondence-rule payload reads as a rule but its content hash differs from its
bundled `rule_id`, the import is refused regardless of `on_conflict`; the importer does
not guess which id the sender intended.
An imported review event whose `event_type` exceeds the column's declared width is
also refused before any rows are written. The refusal shows at most the first 80
characters of the kind and reports its full length and the column width.

For the one-to-one estate binding rule and its warning when an estate keeps its own id,
see [moving a finished comparison](/docs/Genesis-Prover/Overview#move-a-finished-comparison).

| Parameter | Type | Default | Description |
| - | - | - | - |
| `bundle` | object | none | Required `export_comparison` document, passed verbatim. Do not edit its ids. |
| `on_conflict` | string | `refuse` | `refuse` stops at an existing row; `skip` leaves existing rows alone and makes a repeat import a no-op; `replace` overwrites comparison-owned rows. |
| `dry_run` | boolean | `false` | Report the import plan without writing. |

The tool requires `ratify_source_contract`; `export_comparison` requires
`view_connections`. For the REST request and response fields, including conflict status
codes and the transaction behavior, see the [comparison transfer endpoints](/docs/Genesis-API/API-Reference#estate-endpoints).

See the [system diff API reference](/docs/Genesis-API/API-Reference#post-api-estate-system-diffs) for `compare` retry semantics.

`record_review_decision` never invents authority. A run decision is optional once verified
people have accepted every item that kept the comparison off **Verified**; do not ask for a
separate run sign-off to reach that outcome. An explicit reset to `awaiting_review` is a
person's "not approved" and keeps the comparison off Verified until a verified approval
replaces it. The reviewer identity on the record is always the one the server derives —
the authenticated person, or `local operator (auth disabled)` on a deployment running
with authentication disabled. The optional `authority` text is
recorded *beside* that identity, never instead of it, so a local stack's record can still
say who actually made the call. Resetting a comparison to "awaiting review" records no
decision, so it refuses an `authority` note rather than accepting one it would discard.
With authentication enabled, an agent cannot record a verdict at all; it is handed back to
the person.

For the request fields, exact-one rule, byte measurements, and mismatch guidance, see the
detailed [compiled-spec API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-compiled).

Use `get_run` as the only source for a run's outcome: its envelope carries the status,
refusal reason, provenance, and completion state. Use `read_comparison` as the only
source for a comparison result and `read_finding` as the only source for a finding's
decision history; do not reconstruct these records from estate queries, logs, or report
files.

For a finished proof or grade, quote `envelope.report_this` word for word as the record
line. Listing rows from `list_runs` and `find_proofs` do not carry that sentence; call
`get_run` before reporting the run. See [reporting a completed
run](/docs/Genesis-Prover/Agents-And-The-API#reporting-a-completed-run) for the sentence's
contents, grade-classified counts, and how to handle causes the record does not state. For
how stored grades without `spec_seal_state` are read, including older-engine grades, see the
[compiled-grade API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled).

`get_run` late-ruling fields: [coordinate contract](/docs/Genesis-Prover/Agents-And-The-API#drift-findings-declare-their-coordinate).

During shutdown, newly submitted Prover work can be refused before its flow starts; see
[Shutdown and scheduling refusals](/docs/Genesis-Prover/How-A-Run-Works#shutdown-and-scheduling-refusals)
for the run-row behavior.

`prover_tools` replaces the much larger set of Prover tools that grew one-per-route. The
older groups below — `source_contract_tools`, `migration_prover_tools`,
`spec_author_tools` — keep working while teams move across. For acts shared with
`prover_tools`, prefer the newer group; the older groups retain the source-contract,
stimulus, and migration-validator verbs that have no `prover_tools` equivalent.

The exact calls, arguments, return keys and refusal shapes an agent needs are in the
agent-facing reference: `docs/prover/tools.md` in the repository, with
`docs/prover/run-envelope.md` for the run envelope every verb answers with and
`docs/prover/prove.md` for `prove` itself. For the proof summary's always-present
`rounds_used_basis`, see [What a run reports back](/docs/Genesis-Prover/Agents-And-The-API#what-a-run-reports-back).

### Estate registration and code assets

Use `register_estate` to create an estate before characterizing it. Registration checks
that each member connection is reachable but does not scan the database. When the
transform repository is already known, attach it with `code_assets`; each item accepts
`kind="git"` and exactly one of `connection_ref`, `url`, or `bot_git_repo`, with optional
`ref` and `subdir`.

Registration is safe to repeat: when the requested scope is already registered and visible
to the caller, the tool returns that estate with `data.reused: true` and the same
`estate_id`; use `update_estate` to change its definition. A new registration returns
`data.reused: false`. For the exact scope identity, visibility conflict, and fields that
remain owned by the returned estate, including the same-source estates and proof-history
disclosure, see the [estate registration API reference](/docs/Genesis-API/API-Reference#post-api-estate-estates).

Before registering an estate, look up the estates already on its connection with
`find_proofs(source="<connection ref>")`. If the response has several candidates,
`data.resolution.candidates` lists their scopes. Reuse an estate that already covers the
scope you need; register a new one only when none does. Same-scope registration reuse does
not detect overlapping scopes, such as a whole-database estate alongside layer estates.
If you create a redundant estate, identify the existing estate to use in your reply so
others do not rely on an ambiguous name-based lookup.

Registering is not a readiness check. Where the server runs an automatic readiness
preflight, the answer's `data.preflight` names that run and the state it is in
(`run_id`, `status`, `stage`, `basis`), and while it is unfinished the answer's `next`
points at that run rather than at `characterize`. A `stage` of `starting` means nothing
has yet reported on the estate's access, ETL or clonability.

Attaching a code asset records where the code is; it does not read or pin the code. If an
estate response's `next` names `clone_code_assets`, call that verb before
`characterize` so each attached git repository is cloned or each Databricks notebook or
job has its revision captured. If a SOURCE estate has no attached code and is not marked
`source_only`, the response also suggests `update_estate(estate_id=..., source_only=true)`;
use that only when no transform of yours produces the raw data, or attach the transform
with `update_estate(code_assets=...)` instead.

Use `update_estate` for later definition changes. Omitted fields stay unchanged; supplied
`members` and `code_assets` values replace the complete lists, and `code_assets=[]`
clears the attached repositories. An edit that supplies no field is refused. `status`
accepts `draft`, `validated`, or `partial`; `archived` is refused because archiving
requires the estate archive API. If a scope edit is refused because another live estate
already reads that exact scope and the refusal names it, use that estate rather than
registering a duplicate.

After attaching repositories, call `clone_code_assets(estate_id=...)` to download them or
pin a Databricks transform. It returns `cloned`, `captured`, `skipped`, and `failed`
counts plus the updated estate. A `databricks_notebook` has no clone: Genesis makes two
workspace REST calls and stores the notebook's exported-source SHA-256 in `revision`; a
`databricks_job` makes one call and stores the job-settings SHA-256. The workspace is
read as the estate agent on the signed-in user's behalf; an agent call supplies its bot
identity, while an API call uses `estate_char.stimulus.agent_bot_id`. If that setting is
empty and no bot identity is supplied, nothing is read and the call is refused. Set
`force=true` to refresh existing clone references or captured revisions. Then call
`derive_code_lineage(estate_id=...)` to parse cloned trees and connect transforms to the
estate's scanned objects; set `force=true` to rebuild existing lineage. Cloning performs
network transfer and disk writes, while Databricks capture performs workspace reads.

If `clone_code_assets` faults after cloning a repository but before saving the estate's
clone reference, its `next` does not recommend repeating the clone. The repository may
already exist on disk, so repeating the same call can fail with `repository already exists`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `code_assets` on `register_estate` | object\[] or null | `null` | Optional attached git assets. Each item uses `kind="git"` and exactly one of `connection_ref`, `url`, or `bot_git_repo`, plus optional `ref` and `subdir`. `url` is a HOSTED remote (GitHub, GitLab, BitBucket) — a `file://` URL, or a path spelled as one (absolute, or beginning `./` or `../`), is refused; `bot_git_repo` names a repository already on this Genesis instance, resolved on disk with no network clone, and is how a local checkout is registered as a declared artifact source. A Databricks transform is attached as `kind="databricks_notebook"` (`connection_ref` + absolute `workspace_path`) or `kind="databricks_job"` (`connection_ref` + `job_id`); `clone_code_assets` captures its revision (source or settings SHA-256). |
| `source_only` on `register_estate` and `update_estate` | boolean | `false` / omitted | Declares that no transform of ours produces the estate's data, such as raw landing data. Its readiness has no ETL light, so it can read ready with no code assets; the preflight lists the omitted check under `not_applicable`. It does not restrict the estate's role or comparison side. |
| `estate_id` on `update_estate`, `clone_code_assets`, and `derive_code_lineage` | string | `""` | Required estate id. |
| `force` on `clone_code_assets` and `derive_code_lineage` | boolean | `false` | Re-clone git assets or recapture Databricks revisions with existing server-owned state; re-derive assets with existing lineage. |

### `reproduce_artifact`

Run one artifact already present in the estate's derived lineage into a scratch estate,
characterize what it produced, and compare that output with the live relation. This is
the only Prover check that demonstrates what the declared pipeline makes; writer
attribution identifies who last wrote a relation, and lineage coverage identifies what
an artifact claims, but neither rules out a table patched until it matches.

This operation executes customer SQL and writes to the destination. Set
`utility_estate_id` to an estate registered with `kind="utility"`; a live estate is
refused. On a metered engine, echo `relation` in `confirm_relation` or nothing runs and
no pipeline cost is incurred. The operation is expensive: it characterizes the
artifact's inputs, runs the pipeline, characterizes the reproduced and live relations,
and performs a mediated comparison. Reproductions that overlap in one utility estate
are refused rather than queued within a Genesis server; give each deployment its own
utility estate.

The runner executes the artifact's text as SQL statements and ships no notebook runner. A
PySpark, Python, Jupyter, Scala or R artifact can contribute declared coverage through
`derive_code_lineage`, but cannot run here: it is refused by name before the SQL reader
sees it and returns `unmeasured` with an `error` naming the language and saying re-asking
cannot change it.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `estate_id` | string | `""` | Estate whose derived lineage names the artifact and whose relation is being verified. |
| `utility_estate_id` | string | none | Required scratch estate id. It must be registered with `kind="utility"`. |
| `artifact` | string | none | Declared artifact id in the form `<asset>:<file path in the clone>`. Derive lineage before calling. |
| `relation` | string | none | Live relation to compare with the artifact's reproduced output. |
| `confirm_relation` | string or null | `null` | Must equal `relation` on a non-local engine; omit for sqlite, duckdb, and postgres, where the run's spend is local CPU. |

The response returns `verdict` as `reproduces`, `does_not_reproduce`, or `unmeasured`.
`does_not_reproduce` includes `differences` and the finding basis
`artifact_does_not_reproduce`; `unmeasured` includes `error` and is a statement about
the run, not a verdict on the pipeline. Every response includes `what_this_proves`.

### `characterize`

Scan one estate and record what it contains right now. Prefer the estate-bound form
when the database has already been registered: it binds the scan to that estate's
timeline, updates its latest scan, and makes the resulting snapshot discoverable with
`list_snapshots(estate_id)`. An unknown `estate_id` is refused with `kind: "not_found"`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `estate_id` | string | `""` | Optional registered estate id. When supplied, the scan uses that estate's registered connection, scope, and role. |
| `connection_ref` | string | `""` | Saved connection reference for a direct database scan. Required with `dialect` and `database` when `estate_id` is omitted. |
| `dialect` | string | `""` | Source dialect for a direct scan: `bigquery`, `clickhouse`, `databricks`, `duckdb`, `mssql`, `palantir_foundry`, `postgres`, `postgresql`, `redshift`, `risingwave`, `snowflake`, `sqlite`, `sqlserver`, or `trino`. |
| `database` | string | `""` | Database name for a direct scan. |
| `schemas` | string\[] or null | `null` | Optional schemas to include. Omit it for the full source scope. Not accepted with `estate_id`. |
| `excluded_objects` | string\[] or null | `null` | Optional fully qualified objects to exclude. Not accepted with `estate_id`. |
| `objects` | string\[] or null | `null` | Optional object-level scope. Not accepted with `estate_id`. |
| `allow_absent_scope` | boolean | `false` | Allow missing names in a non-empty `objects` scope for a greenfield build. Not accepted with `estate_id`. |
| `absent_scope_basis` | string or null | `null` | Cause that licenses the absence: `relocation` for a not-yet-moved relocation target, or `frozen_build_did_not_produce` when the measured build failed before producing the relations. Required with `allow_absent_scope` on a direct `role="target"` scan. Not accepted with `estate_id`. |
| `build_evidence` | object or null | `null` | Evidence required for `absent_scope_basis="frozen_build_did_not_produce"`: `armed_by`, non-zero scalar `build_rc`, non-blank `error_summary`, `before_side_measured: true`, and offset-bearing ISO-8601 `measured_at`. Not accepted under `relocation` or with `estate_id`. |
| `role` | string | `"source"` | Direct-scan role; use `"target"` for a migration target. The registered estate's role is used with `estate_id`, so passing `role` there is refused. |
| `wait_seconds` | integer | `0` | Optional bounded wait before returning the run handle. |
| `notify` | boolean | `true` | Queue a wake for this thread when the run is terminal, carrying the same handle a poll returns: it arrives on your next tool result if you are mid-turn, or as a new turn once you are idle. While armed, the handle's `next` says so instead of asking you to poll. Set `false` only to check on the run yourself. |

The estate-bound form does not accept `connection_ref`, `dialect`, `database`,
`schemas`, `excluded_objects`, `objects`, `allow_absent_scope`, `absent_scope_basis`,
`build_evidence`, or `role`; conflicting
arguments are refused rather than ignored. Use the direct form only when no estate is
registered for the database. A direct scan binds to no estate, so its snapshot is not
added to an estate timeline and cannot be found later with `list_snapshots`.

When `role="target"` and `allow_absent_scope` is `true`, name why the target is absent:
`relocation` for a declared relocation whose round-0 target does not hold the relations
yet, or `frozen_build_did_not_produce` when the build failed before producing them. The
second cause requires all five `build_evidence` fields and a non-zero build return code;
an unnamed cause is refused instead of allowing an empty target to look like a clean
comparison. The cause is retained in snapshot provenance and used by proof results to
distinguish an unbuilt relation from an unread element.

Both forms return a run handle with `run_id`, `status`, and a poll link. The
estate-bound response also includes `data.estate_id` and the timeline `data.scan_id`.
Poll `get_run(prover_run_id=...)` until the run is terminal; a real estate can take
20–30+ minutes, so an expired wait is not a failed scan and re-running an identical
scan wastes warehouse work. If the same characterization is already `queued` or
`running`, the tool returns that run with `reused: true` and a `reused_basis` explaining
the reuse, and applies `wait_seconds` to the existing run when a wait was requested.
A finished characterization is not reused: it measures a later instant and a new call
starts a new scan. New submissions return `reused: false` and
`reused_basis: null`.

For Foundry, an ambiguous read whose row-cap probe is rejected may require one extra
Spark query to check that read; see [Foundry SQL result caps](/docs/Genesis-Prover/Overview#foundry-sql-result-caps).

For a Foundry run that used the legacy SQL route, `get_run` includes
`summary.source_route_fallbacks` on its terminal summary, including an error terminal
when the run fails after falling back. `fallbacks` counts reads served after the public
SQL route refused them, `reads` is the member's total source-read count, `reason` preserves
Foundry's refusal message, and `cause` is `refused` or `not_served`. In a multi-member
scan, each member's summary has its own counts; they do not accumulate across members.
The key is omitted when no read fell back. The legacy route reads the same source data, so
this records route access rather than indicating a scan failure or a bad result. The
two routes have never been compared for latency, so it does not explain a run's
duration either. See the
[Foundry integration guide](/docs/Integrations/Palantir-Foundry/Palantir-Foundry#test-the-foundry-connection)
for what each route refusal means.

For interrupted-scan isolation, this tool follows the caller-scoped behavior documented
for [`POST /api/estate/characterize`](/docs/Genesis-API/API-Reference#post-apiestatecharacterize).

Example:

```python theme={null}
characterize(estate_id="estate_source")
```

### `list_snapshots`

Call `list_snapshots` first when the user has an estate id but `prove` or `compare`
needs a characterization snapshot id. It returns that estate's scan timeline newest
first. Each scan includes `snapshot_id`, `run_id`, `status`, whether it was the first
scan or a rescan, and `started_at` / `finished_at`. A scan that is still running has a
`null` `snapshot_id`; poll its `run_id` with `get_run` instead of passing the null to a
comparison.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `estate_id` | string | none | Required id returned by `register_estate` and shown on the estate surface. |

Every entry carries `binding`: `bound` means a scan event names this estate, while
`inferred_from_boundary` means the estate's registered connection, database, and optional
schema scope matches a stored snapshot even though no scan event binds it. Inferred rows
keep `snapshot_id` and `finished_at`, but their scan-only fields (`scan_id`, `run_id`,
`kind`, `ordinal`, `status`, and `started_at`) are `null`; `binding_basis` explains that
the link is an inference. This fallback appears only when the estate has no bound scans.

An empty `scans` list is a successful read and now means that neither a bound scan nor a
scope-matched stored snapshot was found. It does not prove that the estate was never
characterized; use `list_runs` to look for an existing `characterize` run for the same
connection before starting another scan. An unknown or caller-invisible `estate_id` is
refused with `kind: "not_found"`. The timeline omits scans naming snapshots the caller
cannot see; fresher-sibling results include only visible estates and snapshots, and
withhold newest-snapshot details when that snapshot is hidden. Their `basis` reflects the
visible sibling rows, so a filtered list does not disclose hidden siblings. The read costs
one visibility-scope load, plus one database read for a bound timeline, or three when it
must match the registered scope against stored boundaries and snapshots.

Example:

```python theme={null}
list_snapshots(estate_id="estate_source")
```

### `find_proofs`

Call `find_proofs` first when someone asks whether a migration has already been checked,
what proof exists for two systems, or whether a person has signed off on the result. It
searches the proof ledger before starting another comparison, and accepts the estate id,
registered estate name, connection reference (`<type>.<name>`), or database / catalog name
that the user actually has. At least one of `source`, `target`, or `spec_hash` is required;
omit either estate side to widen that side of the search.

Estate names resolve and proof results are counted only among estates, comparisons, and
snapshots the person behind the call may see. An inaccessible estate is neither a match
nor a named candidate, and proofs with an inaccessible endpoint snapshot are excluded.
This adds one visibility-scope load per search.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source` | string | `""` | Optional BEFORE-side estate id, registered name, connection reference, or database / catalog name. |
| `target` | string | `""` | Optional AFTER-side estate id, registered name, connection reference, or database / catalog name. |
| `spec_hash` | string | `""` | Optional 64-character lowercase hexadecimal sealed-spec hash; limits results to proofs graded against that spec. |
| `limit` | integer or null | `100` | Number of newest proofs to list per comparison-history pair; must be between `1` and `1000`. `proof_count` remains the pair's true total. See [comparison history and scope](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat) for how schema-scoped scans are grouped. |
| `candidate_limit` | integer or null | `10` | How many candidate estates each withheld side names when the answer cannot assert a proof; must be between `1` and `1000`. `resolution.candidate_count` remains the true total, and the withheld sentence says how many were cut and names this parameter. Raising it costs no further read. |
| `pair_offset` | integer or null | `0` | Non-negative offset for the page of full pairs. Pass `data.pairs_page.next_pair_offset` to read the next page; an offset at or beyond the last matched pair is refused. |

Each result in `pairs` includes `latest_proof`, `earlier_proofs`, `proof_count`, and a
`links.detail` URL for the latest comparison. Proof rows include the run id, comparison
hash, certification verdict and basis, stop reason, and `review_decision`. A reported
`review_decision` always carries `stands`: `true` when the live population was resolved
and the decision accounts for it, `false` when it no longer accounts for the comparison's
current population, or `null` when the live population could not be resolved. `null` is a
failed measurement, not an approval; treat only `stands: true` as a standing run decision.
Each proof also carries `person_acceptance`: when non-null, verified people's standing
approvals cover every item that kept the comparison off **Verified**, so report **Verified**
even when no run decision stands. A person's explicit reset to `awaiting_review` keeps
`person_acceptance` null until a verified approval replaces it. See the [comparison review
API contract](/docs/Genesis-API/API-Reference#get-api-estate-comparisons-diff-hash-review)
for its fields. A standing `review_decision` answers whether the run decision stands, not
whether the comparison is Verified or needs a sign-off; open `read_comparison` and use
`data.review.nothing_to_decide` for that. The
`review_decision_basis` explains the measured or unmeasured result. A retracted exception
that is later re-approved is evaluated by its final state, so it does not leave the
approval withdrawn. A `null` `review_decision` with a basis means either that no
settlement event was recorded or that a re-diagnosis withdrew the decision; read
`review_decision_basis` to distinguish those cases. It never means `declined`. The
response `basis` explains how each named side resolved and discloses a
proof in the opposite direction when no requested pair matched. `find_proofs` includes
both `prove` runs and standalone `system_diff` runs, and labels each pair side as
`bound` or `inferred_from_boundary`.

When several pairs match, read `data.pair_index` first: it names every matched pair with
the estate ids and names, active states, `proof_count`, and the run of record's id, hash,
certification verdict, and review standing. `data.pairs` contains full details for as many
pairs as fit, starting at `pair_offset`; `data.pairs_page` reports `offset`, `returned`,
`total`, `next_pair_offset`, `index_offset`, and `index_returned`. Pass a non-null
`next_pair_offset` as the next call's `pair_offset`. For very large results the index itself
is windowed, and `index_offset` / `index_returned` identify the entries on that page. Each
page first builds its first pair with earlier proofs; other pairs carry only their run of
record and true `proof_count`. If that answer leaves room for more pairs and any of them
has earlier proofs, the search builds in full up to the number of pairs that fit, capped at
five.

For a carried approval, `review_decision.approval_carried_from` on the new comparison
names the comparison and run where the person made the decision, its original author and
time, and the run that carried it here; `review_decision.approval_carried_to` on the
original comparison names the destination comparison and run. A carry preserves the
original decision and is not a new sign-off. The comparison review read also recovers the
destination from older carry records; see `approval_carried_to` in the [API reference](/docs/Genesis-API/API-Reference).

The response also includes `unattributed_snapshots`, which discloses snapshots that
matched more than one unbound estate's registered scope and were therefore left out of
the asserted proof pairs. Its `snapshot_count` is the true total, while `snapshots` lists
at most `20` entries; `snapshots_listed` reports how many entries were returned. Each
entry includes `snapshot_id` and `claimed_by`, whose items identify the competing
`estate_id` and estate `name`. A non-zero count is a subtraction from this answer, not
evidence that the migration was never proved: scan the estate you mean so the snapshot
binds to it, then call `find_proofs` again. When the count is `0`, `basis` reports that
the scope match measured no ambiguity.

Every proof row also carries `source_moved_since_approval` and
`target_moved_since_approval`, one block for each endpoint estate. These are a disclosure
beside `review_decision`, not another approval gate: `stands` says whether the reviewed
population still accounts for the decision, while these blocks say whether the estate
itself has **changed** since the **reading this approval was recorded against**.
When `stands` is `true` or `false`, it is the same revalidated standing reported by the
comparison's Human Review page at `review_url`; when it is `null`, this read could not
resolve the population needed to make that comparison.

`count` is the number of later readings of that estate boundary whose measured content
DIFFERS from the bound one — compared per object on name, type, row count and digest-tree
root. A reading whose inventory could not be compared at all (its object rows no longer
match the count it sealed) is counted with them: "this could not be compared" is never
reported as "this is the same". It is deliberately not the number of later readings: a snapshot id hashes the whole
sealed characterization document, scan-time facts included, so a neighbouring comparison
re-scanning an untouched estate writes a new reading that differs in nothing a reader
cares about. `readings_since` carries that raw number for an audit answer, and
`latest_changed_snapshot_id` / `latest_changed_at` name the newest DIFFERING reading.
Each block always includes `count`, `readings_since`, `basis`, `approved_snapshot_id`,
`latest_snapshot_id`, `latest_at`, `latest_changed_snapshot_id`, and `latest_changed_at`;
`count` and `readings_since` are integers for `measured`, `no_newer_snapshot` and
`no_content_change`, otherwise both are `null`.

`basis` is one of `measured`, `no_newer_snapshot`, `no_content_change`,
`no_standing_approval`, `no_snapshot_bound`, or `approved_snapshot_absent`.
`no_content_change` is a measured zero: the estate WAS read again and every later reading
measured the same content. The last three distinguish an
undecided comparison, a comparison with no bound snapshot, and a bound snapshot that is
no longer retained; they are not reported as zero. For `measured`, `latest_snapshot_id`
and `latest_at` identify the newest reading. The timestamp is normalized to UTC ISO-8601.

A name resolves to a boundary GROUP, not to one estate row: an estate an operator
registered and the `estate_bf_…` twin the boot backfill minted over the same
`dialect:database` are one boundary, and proofs bound to either are proofs of the same
pair. Each pair therefore carries `source_bound_estate_id` and `target_bound_estate_id`
naming the row its run of record is actually bound to; they equal the pair's own estate
ids where nothing was folded. Several rows of one boundary resolve with
`resolution.basis: ["unambiguous_boundary_group"]` and `asserted: true` — that is not
ambiguity. Several estates registered over one physical database are still several
estates, and the answer still withholds.

Each proof row also carries `spec_hash_resolvable` and
`spec_hash_resolvable_basis`; use the [Prover run contract](/docs/Genesis-Prover/Agents-And-The-API#when-the-named-spec-is-no-longer-reachable)
for the basis vocabulary and the pre-contract projection-seal case.

Every proof row in `latest_proof` and `earlier_proofs` also carries `review_url`,
`review_url_basis`, and `review_path`. `review_url` is the absolute Human Review page for
that proof's comparison, where the reported decision is recorded; it is `null` when no
usable address is available, and the key is still present. When a public address is
unavailable, it uses the Genesis address the current conversation came from, or this
server's local dashboard address when there is no conversation address. Use that URL in the
context its basis names; someone reaching Genesis another way may not be able to open a
conversation-addressed link, and a local link opens on the machine running Genesis.
`review_path` is the same page relative to the Genesis dashboard, present whenever the
row names a comparison; use it when `review_url` is null. `review_url_basis` is always
present and has one of these exact values:

* `addressed: this instance publishes a public base URL and the answer names a comparison, so review_url opens that comparison's Human Review page — where the decision is recorded, and where a person makes one`
* `addressed_conversation: this deployment publishes no public base URL, so review_url is built on the Genesis page this conversation was sent from — it opens for the person in this conversation; someone who reaches Genesis another way may not be able to open it`
* `addressed_local: this deployment publishes no public base URL and this conversation names no Genesis page it was sent from, so review_url is built on this server's own local address — it opens on the machine running Genesis`
* `no_public_base_url: this deployment publishes no externally reachable base URL, this conversation names no Genesis page it was sent from, and this server serves no dashboard on an address of its own, so there is no address a person can be handed. The review page is still reachable same-origin from the dashboard; only an absolute link cannot be built here. An operator who wants absolute links sets FASTAPI_BASE_URL (or the GENESIS_PUBLIC_BASE_URL override, which outranks it) to this instance's external address and restarts; SPCS discovers its own ingress and needs neither`
* `no_comparison: this row names no comparison, so there is nothing to review yet — a proof that has not reached its comparison stage has no diff hash to address`
* `address_unreadable: this deployment's public base URL could not be read, so no link could be built — which is NOT the same as this deployment having no public address. The failure is logged at WARNING on the server; the rest of this answer was read normally and stands`

`read_comparison` returns the same three keys beside its always-present `review` state.
Completed `prove` and `compare` answers, their `get_run` polls, and the run-finished
notice carry these fields too. A `null` URL does not change the review result; hand over
`review_url` exactly as returned, with the whole hash, or use `review_path` exactly as
returned as the dashboard handoff. Use the basis to distinguish no usable address from an
address that could not be read on that call. Building the handoff normally reads the
deployment's cached public address once; a cold cache can rediscover the ingress through
the database adapter.

The tool asserts pairs only when every named side resolves to exactly one active
boundary — one live estate (`unambiguous_active`), or several rows of one registered
boundary (`unambiguous_boundary_group`). If a name matches estates of several different
boundaries, matches an archived estate, or matches nothing,
`data.resolution.asserted` is `false` and `pairs` is empty; this does **not** mean that
the migration was never proved. Read `data.resolution.basis`, which can then contain
`ambiguous_name`, `inactive_match`, and `no_match`, and re-run with one registered name
whose candidate has `active: true`. An archived candidate remains non-asserting even when
named exactly; use `list_snapshots`, then `list_runs`, then `read_comparison` to inspect
its history instead.

For a withholding side, `data.resolution.candidates` combines direct matches and near
matches, ordered as live estates first, then estates with a decided pair, then most
recently scanned, then registered name. The order is only a reading aid; it never chooses
an estate. Each candidate includes `side`, `estate_id`, `name`, `active`, `pair_count`,
`decided_pair_count`, and `last_scanned_at`. The list is capped at 10 candidates per
side; `candidate_count` is the true total. `candidate_order_basis` contains the same
ordering explanation returned by the tool. The response also includes
`source_basis` and `target_basis`, while `pairs_returned` and
`candidate_pairs_considered` distinguish the pairs presented from the pairs found for
the resolved estates.

Every returned pair includes `source_estate_active` and `target_estate_active`; an
inactive value means that estate is archived and its comparison is stale by construction.

Every pair also discloses `source_estate_kind`, `target_estate_kind`, `provenance`, and
`provenance_basis`. Branch on `provenance`, not `kind` alone: `synthetic` marks a utility
or drill-clone estate, a synthetic-flagged estate, or a curated adversarial target whose
defects were planted for a rehearsal. Synthetic pairs are exercises, not proofs of record.
When name resolution withholds an answer, the response uses `proof_count: null` rather
than `0`; `candidate_pairs_considered` still says how many proved pairs were found.

`read_comparison` always includes `review`, even when no optional findings or families
are requested. Use it as the comparison's folded review state: it reports the standing
verdict (`awaiting_review`, `approved`, or `approved_with_exceptions`), reviewer
identity and time, and the run and population coordinates attached to the decision.
Read this field before treating comparison counts as sign-off; a clean count is not an
approval.

When `findings` is requested, read each row's `settlement.settled` and
`settlement_basis` rather than its observation fields alone; the complete row and
summary contract, including `settlement_counts` and `settled_at_run`, is documented in
the [estate API reference](/docs/Genesis-API/API-Reference).

Finding rows may also include `family_signature_shape`: `persisted` means the
systemic-family coordinates came from the stored finding row, while `computed` means
the service derived them from the evidence document during this read. When clustered
families are requested, their `signature_shape` is `persisted` only if every member
was placed from stored coordinates; otherwise it is `computed`. This lets an agent
distinguish a normal current read from a store still being brought up to date without
changing the family grouping or requiring a setting. New finding writes persist the
coordinates; existing rows are backfilled automatically at startup, and rows not yet
backfilled remain correct because the service derives them from evidence for that read.
The backfill's batched write strategy is described in [How a Run Works](/docs/Genesis-Prover/How-A-Run-Works#listing-runs-without-the-evidence-payload).

Each search performs about a dozen deployment-wide reads. Pair paging adds no separate
read, but each page starts with a search that builds only its first pair with earlier proofs;
all other pairs carry only their run of record. If the response leaves room for more pairs
and any later pair has earlier proofs, the tool repeats the whole search to build in full
up to the number of pairs that fit, capped at five. That second search builds the first pair
again, and details for pairs that still do not fit may be built and left out. A page with
only one pair, or whose other pairs each have one proof, needs just one search. Each search
fits the response with one serialization and, if needed, a bisection for each list that
must be shortened. The tool is read-only and does not start a comparison.

Example:

```python theme={null}
find_proofs(source="warehouse_prod", target="warehouse_rebuilt", limit=20)
# Continue when data.pairs_page.next_pair_offset is non-null:
find_proofs(source="warehouse_prod", target="warehouse_rebuilt", limit=20, pair_offset=next_pair_offset)
```

### `read_snapshot`

Use `read_snapshot` to answer a row-count question from what a scan measured — how many rows
a table held, which tables a scan found — instead of counting against the live
connection. The counts are as of that scan.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `snapshot_id` | string | required | A snapshot id from `list_snapshots` or a finished `characterize` run. |

Returns `snapshot_id`, `dialect`, `database`, `object_count`, and `objects`: one entry per
measured object with `object_name`, `qn`, `object_type`, `row_count` (`null` when the scan
could not count it), and `digest_root`. An unknown snapshot, or one outside your estates,
is refused with `kind: "not_found"`. The tool reads the snapshot's identity row, its object
rows, and your estate scope; it never loads the characterization document, which the HTTP
detail route decodes in full.

Example:

```python theme={null}
read_snapshot(snapshot_id="snap_bronze_0921")
```

### `list_runs`

Use `list_runs` to discover what the Prover has already run — especially after a bounded
wait expires, when starting the same work again could create a duplicate. Results are
newest first and contain slim run rows: identity, type, status, liveness timestamps,
and summary scalars such as counts, verdicts, and hashes. The per-run evidence blob is
not included; use `get_run` for one run's full detail or `read_comparison` for a
comparison's result. For Databricks spec-drill admission and kept-lease summary details,
see the [spec-drill API reference](/docs/Genesis-API/API-Reference). Runs started in
another conversation that is hidden or that you may
not open remain listed with only `run_id`, `run_type`, `status`, `started_at`,
`finished_at`, and `heartbeat_at`; `contents_withheld` is `true`, `same_conversation` is
`false`, and `conversation_note` explains why. `get_run` refuses those runs with
`kind: "not_found"` instead of returning their contents. For each distinct other
conversation represented on the page, visibility adds an in-memory hidden-flag lookup
and, when it is not hidden, one thread-access check (up to two RBAC permission queries).
The caller's estate visibility also filters runs bound to estates, connections,
comparisons, or boundaries they cannot see: those rows are omitted entirely, and are not
included in the page or `runs_without_estate` count. This adds one run-visibility scope
load for the instance, including a distinct read of run connections and boundary
snapshot/connection indexes. `get_run` answers a hidden bound run with
`kind: "not_found"`, just like an unknown id; see [Prover result
visibility](/docs/Genesis-API/API-Reference#prover-result-visibility) for the shared rule.
For new runs submitted by `characterize_estate`, `grade`, or `author_spec`, the submitting
conversation is recorded even when `notify=false`; `notify` controls the terminal wake,
not this visibility check.
In SQLAlchemy metadata mode, store setup for run listing is automatic; see [Prover run
listing](/docs/Genesis-Prover/How-A-Run-Works#listing-runs-without-the-evidence-payload).

| Parameter | Type | Default | Description |
| - | - | - | - |
| `run_type` | string | `""` | Optional type filter, such as `characterize`, `prove`, `system_diff`, or `spec_conformance`. |
| `estate_id` | string | `""` | Optional named estate. Keeps runs submitted under that estate or compared against it as the proof target, filtered before the page is cut, and adds `runs_without_estate`: how many runs carry neither estate reference and so appear on no estate's page. |
| `limit` | integer | `50` | Number of newest runs to return; must be between `1` and `1000`. This is a page, not a status filter. |
| `cursor` | string | `""` | Optional opaque `next_cursor` from the previous response. Pass it back unchanged to continue with older runs. |
| `shape` | string | `card` | How much of each run to build: `card` (the bounded row — scalars, identity blocks, and any oversized block replaced by a stand-in naming its size), `slim` (five allowlisted summary keys), or `full` (the whole per-run evidence document). Anything else is refused. |

`shape` defaults to `card` rather than to the listing route's `full`, because a `full`
page measured 262,333 B for 18 rows with a single row at 156,766 B and nothing about
"what has been run" needs the evidence documents. Ask for `full` only when you will read
them; one run's detail is cheaper through `get_run`. Every row names its own shape on
`summary_shape`, so "this run recorded no canvas" stays distinguishable from "this shape
did not fetch the canvas".

The response always includes `has_more` and `next_cursor`. `has_more: true` means older
runs exist beyond the returned page; pass `next_cursor` to continue, and do not report a
run as absent just because it is outside the newest page. Rows can include
`stimulus_evidence: true` when the system minted the run as evidence, such as a
`system_diff` produced by a stimulus beat. This is classification, not a filter; the
tool has no status filter. The tool performs two database reads: the bounded run ledger
and the stimulus differential index, plus one batched compiled-spec lookup when returned
rows cite a `spec_hash`, and one COUNT of the runs without either a submitting or target
estate when `estate_id` is given. Each row carries `spec_hash_resolvable` and
`spec_hash_resolvable_basis`; use them to filter out grades whose named spec is no
longer available from this instance.

For `spec_conformance` rows, the summary also retains `scope`: a compact list with one
entry per scoped object, containing `object`, `expectation`, and `status`.
For the unconfirmed-item count retained in card-shaped grade rows, see the [runs API
contract](/docs/Genesis-API/API-Reference).

Example:

```python theme={null}
list_runs(run_type="characterize", limit=50)
```

Each row also carries the common `progress` block and `next_step` sentence. For a
seat-backed run, compare `progress.last_activity` or its counters across calls rather
than treating `phase: "working"` as proof of current liveness; the shared field semantics
are in [Prover run progress](/docs/Genesis-Prover/Agents-And-The-API#prover-run-progress).

### Short hashes

`diff_hash`, `finding_key`, and `spec_hash` are 64-character lowercase SHA-256 digests.
The read tools `read_comparison`, `read_finding`, `read_spec`, `read_proposal`, and
`export_comparison` accept an unambiguous prefix of at least 8 characters. An ambiguous
prefix refuses with candidates, a prefix shorter than 8 is invalid, and a well-formed
prefix naming nothing returns the tool's normal not-found result. Write tools and
`find_proofs` still require the full hash.

Prefixes in comparison and finding hash spaces resolve only against records visible to
the person the agent is working for. Hidden matches are removed before candidates are
counted or named: a prefix matching only hidden records behaves like a prefix matching
nothing, and an ambiguous response lists only visible candidates. If more than 1,000
records match before visibility is applied, the prefix is refused without listing or
counting matches; provide more hash characters.

### `read_comparison`

Read a finished comparison by the `diff_hash` from a proof or compare run. The
comparison itself is always returned; request `findings`, `families`, the recent
comparison-event `events` feed, or comparison `grades` through `include` only when you
need those extra payloads, because each one performs its own read.

When `include` requests `families`, the rollup uses only findings visible to the person
the agent is working for; see [Prover result visibility](/docs/Genesis-API/API-Reference#prover-result-visibility).

When `include` requests findings, a duplicated-load finding may include bounded repeated
key examples in `relied_on.sample_keys`. The examples are illustrative; the counts decide
the finding. See the [Prover comparison guide](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff)
for the limits and when they are read.

The response also carries the same `presented` comparison card returned by `prove`,
`compare`, and `get_run`; it is built from this comparison and replaces an earlier card
for the same comparison in chat. When this comparison was commissioned by a proof,
`presented.proof_run_id` names that proof run so chat can join the comparison to the
proof's running card. Resolving this field costs one indexed run-row read.

When present, `presented.spec_grade` includes the grade's `blockers` and
`blockers_total`; on a paired comparison, `accounting.outside_scope` and
`accounting.outside_scope_total` carry the spec-scope disclosure. Each list is capped at
five entries, with its total preserving the full count. See the [review-population API
contract](/docs/Genesis-API/API-Reference#get-api-estate-comparisons-diff-hash-review-population)
for the grade's accounting fields and \[comparison cards in chat]
(/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat) for how to interpret it.
When a grade covers only selected checks, `presented.spec_grade` also carries
`spec_seal_state: "subset"`, `graded_check_ids`, and `spec_check_count`; these fields name
the graded checks and total spec check count. See \[the Prover card guidance]
(/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat) for how the card presents
this grade.

Resolving `presented.spec_grade` costs two indexed reads. When the tables paired, it also
costs a bounded indexed join of this comparison's population runs (at most 129 run rows,
with their summaries) and a read of in-flight spec proofs. When the tables paired none,
it instead scans the uncapped `spec_conformance` and `spec_drill` run feeds and reads the
documents of runs grading this comparison, plus the in-flight proofs. The paired path is
bounded by this comparison's population; the no-pair path grows with deployment grading
history.

The `data.review.person_acceptance` and `presented.person_acceptance` fields carry the
reviewed outcome; see the [comparison review API contract](/docs/Genesis-API/API-Reference#get-api-estate-comparisons-diff-hash-review)
and [comparison-card guidance](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat)
for their meaning and response shape. Resolving them folds the review log; when a verified
person's exception stands on the comparison it may also resolve the population, whether or
not a run decision exists, and only when the outcome otherwise stands does it scan the
uncapped `stimulus` run feed and fold the scoped finding ledger. The
detailed review item list also reads the complete population and its findings ledger.

`data.review.decision_approval_basis` identifies the basis for the current run-level
verdict and, for an agent decision, the person, agent, conversation, goal, and server-known
turn context. It is `null` when no verdict stands or when the record predates this field;
see the [comparison review API contract](/docs/Genesis-API/API-Reference#get-api-estate-comparisons-diff-hash-review)
for its structured fields.

`data.review.nothing_to_decide` is `true` when the comparison reads **Verified** and no
person has reset its run decision; otherwise it is `false`. This applies to `scope` too
when its card has a measurable errored count; an unknown count is not an all-clear. A true
value means nothing is left for anyone to decide, even when `data.review.decision` is
`awaiting_review`: a run decision is optional and does not make a comparison Verified.
Report **Verified** without asking for a sign-off or staging a package. When it is false,
the grade blockers and open differences identify what remains.

With `include=["findings"]`, `data.findings.person_acceptance` carries the same outcome
without its item list, and each finding row carries `person_accepted`. A `true` row means
the person accepted that finding and the comparison reads **Verified**; report it as
accepted even when its machine `state` remains `still_open` (the difference is still
observed). When `person_acceptance` is `null`, every row's `person_accepted` is `false`.
The `finding_keys` shape does not carry either field.

Platform-type, unique-index, rewritten-view, source-built-output, and value-proven
TIME-as-text assumptions may appear in `comparison.assumptions`; see [Genesis Prover's
assumption rules](/docs/Genesis-Prover/Overview#fresh-licensing-evidence)
and the [comparison behavior](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff).

Comparisons produced with float tolerance also include `summary.float_tolerance`, keyed
by `object.column`, with `elements` and `max_relative_difference` for each entry. Read
the [Prover comparison guide](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff)
for the tolerance rule and when the comparison performs live value reads. The comparison
summary also records `float_tolerance_read` and `time_text_read`: requested columns, how
many were read on both sides, and the cause and reason for each unread side. The same
`float_tolerance_read` block is projected at `summary.comparison_counts.float_tolerance_read`
when run counts are returned; older comparisons without that block report `null`.

For the `summary.undeclared_target_shape` guidance and withheld-reading fields returned
by `read_comparison`, see the [review population API contract](/docs/Genesis-API/API-Reference#get-api-estate-comparisons-diff-hash-review-population).
When the guidance describes a pair with no one-to-one correspondence, use its `unpaired`,
`observation`, and `target_model_example` fields as instructions to declare the mapping;
shared columns are observations, not an inferred mapping. If the response has
`nothing_compared: true` and no verified `spec_grade`, do not present the comparison as
approvable. Follow the refusal's
`next`: declare the mapping and reseal the spec, re-prove with a `schema_map` when the
comparison matched zero objects, or run the comparison again when no matched count is
recorded for it. If a reshaped build's `spec_grade` is not verified, the refusal instead
names its blockers and directs the agent to `read_comparison` before fixing the build or
spec and grading it again.

Whether a specification was graded is a comparison-level question: the proof's run names
only the specification it ran under, and another grade may have been submitted against the
same comparison later. Request `include=["grades"]` before saying whether a spec was
attached or what a grade found. `data.grades` lists each viable grade, newest submission
first, with its `run_id`, `run_type`, `status`, `submitted_at`, `finished_at`,
`shown_on_review`, `specification_attached`, `spec_name`, `spec_hash`, `sealed_at`,
`submitted_by` (`principal`, `operator`, `surface`), `outcome`, `outcome_headline`,
`obligations`, and `accounted_for`. `shown_on_review: true` identifies the grade the review
page opens. Running grades are included; crashed grades and finished grades without a view
are not viable and are omitted. A grade's outcome describes its checks, not whether the
comparison matched any tables: when `data.comparison.matched_count` is `0`, report both the
zero-match comparison and the grade's own outcome. Grades started in a conversation the
reader cannot open are listed with `contents_withheld: true`; report only that such a grade
exists. An empty `grades` list means no viable grade was recorded.

When `presented.spec_grade.open_clauses` is greater than zero, use the grade run's
`summary.open_clauses` for each clause's reason, remedy and evidence. Follow the [Prover
partial-seal reporting and remedy rules](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat)
when presenting or acting on those clauses.

This include is opt-in because it costs the uncapped grading-run feed scan: two slim feed
reads, the stimulus-feed harvest, and one batched read of surviving grade documents, plus
per distinct other conversation a hidden-flag lookup and at most one thread-access check.

For a declared-target zero count, use the [Prover mapping guidance](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes).
When `read_comparison` returns `withheld_unlicensed` or `withheld_indeterminate`, follow the
[Prover comparison-card guidance](/docs/Genesis-Prover/Overview#declared-data-vault-target-shapes)
for presenting each withheld count beside its published headline and deciding what to do
next.
When `data.comparison.unwitnessed_by_identity.sentence` is present, relay it rather than
describing findings without witness rows as an evidence gap; see the [Prover comparison
guide](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff). Included finding rows
also carry `rests_on_reopened_seal`; follow the [API field guidance](/docs/Genesis-API/API-Reference#get-api-estate-findings-ledger)
when interpreting that notice.
The completed comparison may include `summary.unaccounted_sources`; follow its
`next_step` before presenting table-level missing readings.
If `summary.unassessed_sources` appears, follow its `statement`; see the [Prover mapping
guide](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes).
The review population's `comparisons_matched` field records the engine's matched count when
one was recorded; use `0` to choose `schema_map` re-proving and `null` to choose a comparison
re-run, while a pair with no one-to-one correspondence needs a declared mapping.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Required comparison hash from `envelope.summary.diff_hash`. |
| `include` | string\[] | omitted | Optional extras: `findings`, `finding_keys`, `families`, `events`, `grades`, or `license_audit`. Omit for the comparison alone. `findings` and `finding_keys` are two shapes of one population and are mutually exclusive. `license_audit` must be requested alone. `grades` lists the comparison's viable grading runs, including grades submitted separately from its proof. |
| `comparison_shape` | string | `full`, except `scope` when `include` names `families` or `finding_keys` | How much of the comparison itself to build: `full` decodes the element document and carries `errored_reads` and `clean` derived from it; `scope` reads the same row without that document and omits those three rather than reporting unmeasured zeros. Its returned card can still carry a measured `errored` count derived as `not_measured.count - indeterminate_count` when both stored counts are whole numbers and the difference is nonnegative; otherwise that count stays unknown. A rollup include (`families` or `finding_keys`) selects `scope` unless you explicitly request another shape. |
| `events_limit` | integer | `25` | Maximum comparison events when `include` contains `events`; clamped to `20000`. |
| `verdict` | string | omitted | Optional element filter. Allowed values are `match`, `licensed`, `unlicensed`, `indeterminate`, and `errored`. Refused with `comparison_shape="scope"`, which reads no elements, and refused beside a rollup include. |
| `settlement_basis` | string | omitted | Optional finding filter: `person_ruled`, `instrument_void`, `closed_by_diff`, or `unsettled`. Applied before the page is cut. Anything else is refused. |
| `family_signature` | string | omitted | Optional finding filter to one systemic family, applied before the page is cut. |
| `family_status` | string | `open` | Family status to roll up when `include` contains `families`; it does not filter finding rows. |
| `offset` | integer | `0` | Finding-row offset. |
| `limit` | integer | server page size | Maximum finding rows to return. |

Every response also carries `data.populations`, which keeps the two comparison
populations separate. `data.populations.elements.total` is the whole recorded
outcome denominator (`match + licensed + unlicensed + indeterminate + errored_reads`);
`differing_or_indeterminate` and its legacy alias `decided` are the narrower
`licensed + unlicensed + indeterminate` subtotal. `data.populations.findings.total`
is the separately scoped durable-ledger count when this call read findings, and is
`null` when it did not. Do not add the two totals or call either one “the differences”
without naming its population; `data.populations.why_they_differ` explains the scopes.
Counts that this response did not measure are `null`, not zero. The block is projected
without another query, so reading it adds no I/O cost.

The completed comparison also carries `data.comparison.object_presence` and
`data.comparison.not_measured`. Use `object_presence` to say which source objects the
target holds, including exact counts and bounded lists of `missing`, `undetermined`,
`absent_as_declared`, `present`, and surplus objects; its `not_built` list separately names
missing derived targets. Use `not_measured` to report every indeterminate or errored reading
and its cause. Both blocks are `null` for comparisons recorded before these disclosures
existed. Do not infer presence from a table list or treat an omitted reading as a clean
result; see the \[comparison API contract]
(/docs/Genesis-API/API-Reference#get-api-estate-comparisons-diff-hash-review-population)
for the field shapes and bounds.

`read_comparison` returns the completed comparison's run context alongside its populations;
see the [comparison API contract](/docs/Genesis-API/API-Reference#get-api-estate-system-diffs-diff-hash)
and [the Prover comparison guide](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff)
when presenting those additional fields. For the new endpoint-estate detail fields, see
the [comparison detail API contract](/docs/Genesis-API/API-Reference#get-api-estate-system-diffs-diff_hash).

Full-shape tool answers prepend a bounded `data.which_proof_applies` summary ahead of the
comparison payload. It groups rewritten views by kind with counts, a shared sentence, up to
five named examples with their reasons (and, for a view whose proof run is named, its
`test_case_coverage` sentence), and a count of omitted views. `same_text_views` and
its shared reason cover unchanged definitions; `next_view` points to the view for the next
step. `full_list` locates every per-view record at
`comparison.which_proof_applies.views`; use it if the sample misses the view you need.
Scope reads omit this summary because they do not read views. See the \[API field contract]
(/docs/Genesis-API/API-Reference#get-api-estate-system-diffs-diff\_hash) for its exact shape
and [Prover guidance](/docs/Genesis-Prover/Overview#rewritten-views-and-behavior-proofs)
for what to do next.

When `include` names `families` or `finding_keys`, the requested rollup is the shape of
the whole comparison, so the tool reads it at `comparison_shape="scope"` by default.
Do not combine that rollup with `comparison_shape="full"` or `verdict`: those options
need the element document and are refused because the rollup and its elements are two
reads. Read the rollup first, then make a separate full, optionally verdict-filtered
call for the elements. Every response also carries `data.comparison.value_coverage`,
which says how many column values and whole-table checksums were compared, how many were
not, and why; a `null` block means the comparison predates this disclosure and is
unknown, not proof that all values were compared. See the \[Prover comparison guide]
(/docs/Genesis-Prover/Overview#2-comparison-the-system-diff) for its counting basis.
When `value_coverage.recharacterize` is present, its `readings` count identifies refused
value readings that can become comparable after re-characterizing the snapshots named in
`recharacterize.snapshots` for the sides listed in `recharacterize.estates`, then
comparing again. `recharacterize.build_version` is the library version whose recipe the
new snapshots must share. When `recharacterize.cause` is
`instrument_version_mismatch`, every value reading in the pair was withheld because the
two snapshots were measured by different known library versions: name the snapshot ids
in `recharacterize.snapshots` for the sides in `recharacterize.estates`,
re-characterize those estates, and compare again. If the cause is
`digest_family_mismatch`, only the readings counted in the block can be repaired by that
re-scan; any remaining readings stay `not_compared`. When `recharacterize` is `null` for
`instrument_version_mismatch`, a side's measurement library version was not recorded, so
the comparison cannot identify which side is stale; its affected element reads
`unknown` for that side's `source_value` or `target_value`, and the user may
re-characterize that snapshot before comparing again.

When `data.comparison.not_measured.by_cause` contains
`observation_skew_append_only`, `observation_skew_mutable`, or `wall_clock_dependent`,
`read_comparison` also returns `data.timing_rescan_evidence`. Its `timing_causes` gives the
matching cause counts, and `sides.source` and `sides.target` each report the later-reading
evidence for that estate. Read the side's `basis` and quote its `statement`; this evidence
does not change the comparison's recorded verdict. `unchanged_on_rescan` means the compared
and later readings have the same content fingerprint and every abstaining object was measured
and equal on both. `unchanged_fingerprint_only` means the fingerprints match but the abstaining
objects were not all checked or located, so their equality is not established.
`abstaining_objects_unchanged` means the estate changed elsewhere while every abstaining
object was checked and held the same row count and digest; `others` names those other changes.
`listed_abstaining_objects_unchanged` makes that claim only for the listed abstaining objects
when the comparison's listing was truncated. `changed_on_rescan` means the content changed;
`not_comparable` means a fingerprint is missing or differing fingerprints cannot be compared
across different or unrecorded measurement-library versions. `no_later_reading` means the
compared reading is still the newest; `compared_snapshot_unplaced` means the compared snapshot
cannot be found or placed on the timeline. The `statement` names both snapshot ids and seal
times when a later reading is available. Equal readings show no net change between those
readings, cannot rule out a reload or revert in between, and never establish a verdict. If
`sides` is null, `unreadable` gives the reason and no conclusion is established.

For large answers, `data` serializes `timing_rescan_evidence`, `review`, `populations`,
`comparison_shape`, and the review links before `comparison`; `comparison.payload` is last
within the comparison, followed by other returned fields such as requested projections. A
truncated preview keeps the serialized head, so check it for the decision evidence before
reading the spilled output. This ordering prioritizes those fields but does not guarantee
they all fit when the leading blocks themselves are too large.

Placement follows the compared snapshot's estate, not its observation boundary: a later scan
of the same estate can be used even when the estate's scope or contract changed between scans.
`placed_by` is `estate` when scan events bind the compared snapshot to an estate, and `boundary`
when no estate owns it and its boundary is the only identity available. `cross_boundary` is true
when the compared and later readings have different boundaries. In that case, a fingerprint
difference alone does not establish a content change: rely on the abstaining objects checked
one by one. A moved abstaining object supports `changed_on_rescan`; unchanged row counts and
digests for every abstaining object support an unchanged result. If those checks do not decide
the abstentions, the result is `not_comparable`. Objects present on only one side of a
cross-boundary whole-inventory comparison are described as scope changes, not content changes.
For the target side, `abstaining_objects` names target objects: it uses each element's
`target_object`, then the comparison's recorded pairing, and falls back to the source name when
neither supplies a target name.

This evidence is read automatically. With timing abstentions, it looks up each snapshot's
owning estate and, when bound, that estate's scanned snapshot ids; it also reads both estates'
snapshot timelines. If a target object name is absent from the comparison elements and its
payload is not already available, it reads the recorded object pairing. For each side with a
later reading it reads the two measurement-library versions; when abstaining objects are
listed, it also reads both snapshots' object rows. If it does not settle the abstention, use
`list_snapshots` to find same-side snapshots sealed before and after the comparison's two
reads, then use `read_snapshot` to compare the disputed objects' `row_count` and `digest_root`.
Equal readings show no net change across the gap, but cannot rule out a reload or an update and
revert in between; report that conclusion as an inference, not as an engine finding. A null
reading is not evidence.

Change stamps can add evidence when their latest value predates both reads, but this only rules
out a stamped write on the source: a target stamp is usually copied from the source, and a hard
delete does not update one. Label values queried outside the recorded comparison as your own
readings. For `wall_clock_dependent`, only the same-side snapshot check applies to change
stamps. If the record does not settle the abstention, offer or run a narrowed re-scan of only
the disputed objects.
Compare each side's past scan duration first; starting both scans together does not mean they
read at the same time. Re-scan each side with `characterize(connection_ref=…, dialect=…,
database=…, objects=[…])`, adding `role="target"` on the target, and prove the returned snapshot
ids. These snapshots are not bound to an estate and will not appear in `list_snapshots` later.
Keep the comparison's verdict as `indeterminate`; state separately which evidence supports or
rules out timing as the cause.

See the [Estate API reference](/docs/Genesis-API/API-Reference#post-api-estate-system-diffs)
for comparison engine provenance and retired-engine response behavior.

Request `include=["license_audit"]` when you need the stored evidence behind a licensing
explanation, an audit trail, or the question of what licensed a difference. This bounded
projection selects `comparison_shape="audit"`, returns `data.license_audit` without
individual element payloads, and includes exact verdict totals, bounded comparison rows,
an aggregate remainder that preserves reconciliation, licensed provenance attributions,
and the used correspondence-rule ids. It must be requested alone. Check its `coverage`
and `truncated` fields before treating variable collections as complete, quote raw
provenance labels exactly, and read each returned rule dossier separately with
`read_correspondence_rule` rather than inferring a rule name or meaning from a label. See
the [Estate API reference](/docs/Genesis-API/API-Reference) for the dossier's sign-off
route and bundle-hold fields.

When `include` contains `families`, the rollup is scoped to the comparison's own estate
pair—the two estates it compares—not only to their engine corridor. The response includes
`data.families_scope` with `component_pair`, `pair_fingerprint`, and `status`, so the
population is explicit. `component_pair` identifies the shared engine corridor, while
`pair_fingerprint` identifies the concrete estate pair whose comparisons contributed to
the families. If the comparison or its snapshots cannot resolve that estate pair, the
tool refuses instead of returning families from every migration on the same corridor.

`comparison_shape` is how a caller paging findings declines the element document. The
comparison does not change between pages, and the default re-sends all of it on every one:
86,682 B per call on a 177-finding comparison, 1.56 MB across the eighteen pages it takes
at `limit=10`. Read the comparison once at `full` if you need the element tallies, then
page at `scope`. `data.comparison_shape` names the shape on every response.

`include=["finding_keys"]` returns the same population as `findings` projected to
`finding_key`, `event_role`, `object_name`, `column_name`, and `last_seen_diff` — what
`propose` reads, without each row's decoded evidence and disposition trail. Use it when
you are enumerating a comparison in order to disposition it. The `limit` is an upper
bound: the tool fits the keys page to `tools.output_governor.inline_budget_bytes` after
assembling the whole answer, including the comparison, populations, `presented`, and
pagination metadata. The response rewrites `returned` and `next_offset` to describe the
keys actually delivered; continue with `next_offset`, never by adding `limit` to `offset`,
until it is `null`. The page targets at least one key; if the complete answer still exceeds
the budget, delivery may shorten other lists while keeping the keys metadata honest.

`settlement_basis` and `family_signature` narrow the comparison before the page is cut, so
they filter the population rather than the page. `settlement_counts` continues to report
the whole comparison's split beside a filtered page, so every count arrives with its
denominator.

Element details may carry `cause="not_compared_by_design"` or
`cause="derived_target_not_compared"` for these skipped digest readings; see [declared
target mappings](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes)
for their approval meaning.

Only `match` means checked and equal. `indeterminate` means the comparison reached
the data but could not determine the result; `errored` means the read itself failed
before producing a measurement. Both are **UNMEASURED**, never clean. Count them as
unresolved rather than folding either into a match total. An invalid `verdict` is
refused instead of silently returning an empty payload.

<a id="source-contract-tools" />

## `source_contract_tools`

Use `source_contract_tools` for source-contract mining, jitter qualification,
and deviation triage; it also exposes `design_stimulus_campaign` for those
workflows. For a rewritten-view behavior proof, activate
`migration_prover_tools` instead: it exposes the same design tool alongside
the proof lifecycle tools, without requiring the larger source-contract group.
For comparing estates, grading a spec, or reading a comparison or finding back,
use `prover_tools` instead. The group includes `register_execution_profile` for
one source or target estate, `preflight_databricks_job_contract` for reading the
canonical contract of a deployed Databricks Job, and `prepare_migration_prover` for the approved,
credential-free contract that `validate_migration` executes. It also includes
the independent Adjudicator seat for reproduce-first triage of a completed
comparison. Credentials are resolved from `connection_ref`; never put credentials
in a profile payload.

The stimulus submission tools consume the pair contract resolved for the run. On a
contract-governed pair, submit rows by logical table name and keep each row inside
that table's declared island; the server maps the logical name to each side's
physical relation and refuses a row that is missing the declared island column or
below its inclusive floor. A contract-less run uses the disclosed legacy default
instead. The REST preflight and run response describe the resolution, refusal, and
legacy-disclosure fields in the [stimulus API reference](/docs/Genesis-API/API-Reference#get-api-estate-stimulus-preflight).
For the administrator-facing permission labels used in tool refusals, see the
[RBAC Practical Guide](/docs/Security-Controls/RBAC-Practical-Guide).

`list_reconcile_episodes` filters the newest `limit` episodes after fetching them;
`limit` defaults to `25` and is capped at `200`, so raise it before concluding that no
visible episode exists. With the ruling overlay active, `list_court_dockets` returns an
empty list for an estate the caller cannot see; reading or deciding a docket there uses
the unknown-docket refusal.

Every verb in this group refuses an argument it does not offer by name instead of
silently dropping it. The refusal names the fields in `unrecognised_arguments` and
confirms that nothing was run; runtime context fields injected by Genesis remain
internal and are not caller arguments.

An exception that escapes a Prover-family verb is returned as a structured
`refusal.kind: "fault"`, not as an unclassified tool error. A fault is an outage,
not a decline: do not report it as a refusal of the request. Follow its `next`
guidance instead. For tools whose repeat could start the operation twice, `next.verb`
is `null`; first read the durable run, status, or list record and retry only when
that read shows that nothing started. Tools that can safely re-read the same act
provide the original verb and caller-supplied identifiers in `next`.

For machine-checkable predictions, write `mart` as the contract locus (`raw.<logical_name>`
for an input or `marts.<logical_name>` for a derived relation). The checker keeps that
logical locus as the identity used for spec coverage, then renders the declared relation,
column spelling, and key predicate independently for the source and target; a locus that
does not resolve uniquely is not checkable. A physical `schema.name` spelling is accepted
only when it maps back to one declared locus, so prefer the logical form in authored
specs. Sealed specs also translate side-physical loci through the same contract before
coverage and silence checks; see [How a Run Works](/docs/Genesis-Prover/How-A-Run-Works)
for the run-level guarantee.
Cross-run migration history classifies `column_element_counts` findings—the
number of elements held by an array column differs—as the `value` phenomenon,
grouping them with other measured-content findings.

The source-contract attribution tools report the author held by each durable row,
not a caller-supplied name. A repeat submission of identical content keeps the
first author, so callers must use `attributed_to_another` before describing the
result as their own. A missing signed-in user is shown as `unattributed`; when no
row was registered, or a row names nobody, the verdict is `null`.

<a id="logic-path-coverage-claims" />

### Logic-path coverage claims

Pass the optional `manifest_path` (string, default `""`) to `design_stimulus_campaign`
to enumerate coverage points from the dbt manifest's model SQL. Copy a point's
`claim_tag` into the corresponding case's `tags` array. In a
`run_trajectory_campaign` mutant, `claimed_coverage` is an optional list of strings; each
entry is a point tag in the form `coverage:<statement-digest-prefix>:<point-id-prefix>`,
or the same two prefixes without `coverage:`. Both prefixes must be at least 8 characters.
A bare point id or a tag for a different SQL text is reported as stale and credits no
point; re-affirm the claim against the current SQL text. Claims that match no point,
match multiple points, or have an unsupported shape are returned separately rather than
silently credited.
When an OR condition is listed as separate alternatives, design a case for each one. A
filter or output column made wholly of alternatives also needs a case for the outcome when
none holds, claimed with the condition's own `claim_tag`; the alternative tags do not claim
that outcome. For how Prover accounts for these claims in a view approval, including CASE
rules shown through their alternatives, see
[Approve test cases for a view](/docs/Genesis-Prover/Roles-And-Approvals#approve-test-cases-for-a-view).

For rewritten-view test cases, `design_stimulus_campaign` also accepts optional
`view_pairs` (array of objects, default `null`). Each pair names `original` and
`rewritten` as `SCHEMA.VIEW`; optionally set `original_boundary_hash` and
`rewritten_boundary_hash` when either view was scanned under another boundary. The tool
reads the newest stored snapshot for each boundary, not the live warehouse, and returns
each view's stored text and a logic outline with a `claim_tag` for each listed path.
Each pair must provide non-empty `original` and `rewritten` strings; malformed pairs are
refused before the design runs. For example:

```python theme={null}
design_stimulus_campaign(
    boundary_hash="<boundary_hash>",
    view_pairs=[{"original": "RAW.ORDERS", "rewritten": "MART.ORDERS"}],
)
```

Pass `include_view_text=false` (boolean, default `true`) to omit both text and outlines
while retaining the claims check. At most five pairs are read per call; each side includes
up to 20,000 characters of text and 30,000 characters of outline, with a combined
200,000-character limit for the call. A stored snapshot that still contains a line
comment may have an incomplete outline; the side reports this as a problem. Rescan that
boundary to refresh its stored text, because the current scanner removes line comments
before storing a view definition.

Put the outline's `claim_tag` values in the corresponding cases' `tags`. To check those
claims without storing the cases, call `design_stimulus_campaign` with `view_pairs`,
`specs`, and `check_claims_only=true` (boolean, default `false`). The response reports
credited, stale, unknown, ambiguous, and unrecognised claims with a summary and a fix
suggestion; claims never block a design run or preparation. Check-only requires at least
one pair and otherwise returns an invalid-pairs error. Use this check before passing the
cases to `prepare_migration_prover`, which stores them itself; do not first store those
cases in a normal design call because they stay bound to that call's boundary. Pass the same
`view_pairs` to preparation to get the claims report without the view text or outlines.
Claims are checked for specs whose `output_relation` names a listed view, or, when it names
no listed view, whose dbt `target_node` ends with one of the pair's view names.
`specs_matching_no_view_pair` counts submitted specs that none of the listed pairs checked.

### Attribution fields on source-contract tools

| Tool | Parameters | Attribution in the response |
| - | - | - |
| `anchor_evidence_ledger` | `contract_id` (string, required), `reference` (string, `""`), `method` (string, `""`; uses `estate_char.attestation.anchor_method` when omitted) | Returns `created_by` and `attributed_to_another` alongside the anchor fields. An existing content-addressed anchor keeps its first author. |
| `design_stimulus_campaign` | `boundary_hash` (string, required), `specs` (object\[], `null`), `contract_id` (string, `""`), `manifest_path` (string, `""`), `component_pair` (string, `""`), `migrator_id` (string, `""`), `view_pairs` (object\[], `null`), `include_view_text` (boolean, `true`), `check_claims_only` (boolean, `false`) | Each `specs_registered` entry includes `designed_by`; the response includes `attributed_to_another`. Identical registered content keeps its first designer. View-pair behavior and claim checks are described above. |
| `backfill_foundry_campaigns` | `limit` (integer, `null`; omitted scans every contract) | Each `campaigns` entry includes `created_by`; the response includes `attributed_to_another`. Existing content-addressed campaigns keep their first backfiller. |

Contract-addressed tools act in the visibility scope of the person the agent is working
for. `get_source_contract`, `verify_source_contract`, `run_jitter_campaign`,
`run_clone_jitter_campaign`, `export_attestation`, and `anchor_evidence_ledger` answer a
hidden contract exactly as an unknown one (`Unknown source contract: <contract_id>`);
they check before reading details or starting work. Each check costs one visibility-scope
load beside one contract read. `get_jitter_campaign` treats a campaign on a hidden
contract as unknown after reading the campaign, while `list_estate_deviations` returns an
empty list for a hidden contract; each adds one scope load and one contract read.

### `verify_attestation_signature`

Check the signature and content claim of an exported attestation without changing it.
The tool returns its signature verdict and lifecycle status, and re-derives the bundle
when the original snapshot is still stored. It requires a signing key and a signed
attestation; use `export_attestation` to create the evidence package.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `attestation_id` | string | none | Required id returned by `export_attestation`. |

An attestation the person you are working for cannot see is answered as unknown before
verification, just like an id the store does not hold. This check costs one visibility
scope load and one attestation-subject read before verification.

### `prove`

Use `prove` after both sides have been characterized. It is the agent-facing
entry point for the Prover's one-trigger flow; the [API reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs)
defines the proof lifecycle and envelope. Omit `spec_hash` for a comparison-only
run, or provide a sealed hash to include grading in the same proof.
The comparison-only `compare` tool takes the same required `title`; `grade` also
requires one when grading an existing comparison.

When a sealed spec declares a target model, attaching `spec_hash` makes the comparison
run under that model before grading. If you instead grade a `compare` result made without
the model, the grade may recompute the pair under the spec; see [when a grade names a
comparison made without its spec](/docs/Genesis-Prover/Overview#when-a-grade-names-a-comparison-made-without-its-spec)
for how the recomputation carries the comparison's `column_map` and `row_identity`, and
reports a key that does not pair rows under the model.

For a no-spec `prove` or `compare`, `change_expectation="must_match"` declares a
lift-and-shift premise: a clean comparison is answered with `next.verb: "propose"`
for a human decision. `must_differ` records that the target should change but still
leaves the caller to author a specification; see [how the Prover handles declared
no-spec shapes](/docs/Genesis-Prover/Overview#2-comparison-the-system-diff).

When a bot calls `prove` for a user, estate reads use the authenticated user's
identity for connection access while the bot remains the acting principal. A
personal connection therefore must belong to the submitting user; see the
[proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs)
for the identity distinction.

Retries reuse a proof only for the same acting bot and authenticated user. Repeating
the same estate question from another identity starts a separate proof; it does not
return a result created for the other identity.
See [comparison cards in chat](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat)
for title handling on reuse.

The tool returns a run handle immediately by default. With `notify` (the default) the
thread that started the proof is told when it reaches a terminal status — on its next
tool result if it is mid-turn, or as a new turn once idle — with the same handle a poll
would return, so there is nothing to poll; poll
`get_run(prover_run_id=run_id)` only when you set `notify=false`. Set `wait_seconds` to
wait inline before the tool returns; the proof continues in the background if the wait
expires. With `spec_hash`, either connection id may be omitted; `prove` resolves available
defaults from the sealed spec's seat. If the seat record does not supply a needed id, pass
that connection explicitly. When a connection is omitted, default resolution reads the
spec's provenance and, if it names a thread, looks up that seat run. Attaching a
specification requires the `ratify_source_contract` permission. A comparison-only proof
requires only the source and target snapshots.

The related `compare` tool uses the same `notify` behavior and default. Its terminal
wake carries the comparison's run handle, and `notify=false` leaves `get_run` as the
polling path.

A wake delivered as a new turn goes through the thread's mailbox, which caps a message
body. When the full handle does not fit, the wake keeps the envelope and every scalar of
its summary and replaces the summary's nested blocks with `summary.omitted_from_wake`,
which names the keys left out and the `get_run` call that returns them. A record that
does not fit even in that form arrives as the notice alone, saying so and naming the
call that reads it; no mailed wake is ever cut by the mailbox. A wake that arrives on a
tool result carries the whole handle.

The proof owns its comparison and grade child runs for notification as well as for the
result: while the proof is still running, a child completion rides the proof's terminal
wake instead of creating a second thread notice. If the proof has already ended or gone
away, the child can still announce its own terminal state.

Submit-time artifact, field, and connection preconditions—including the terminal
`refused` response for an unregistered connection—are documented in the [proof endpoint
reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs).

A graded proof can also be refused before submission when the sealed scope cannot be
paired to the complete snapshot pair. Correct an unresolved scope name and reseal, or
declare the missing `schema_map` (and an `object_map` when object names differ); see the
[proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs).

For the pre-comparison `grade_reads_no_comparison` refusal when `tiers` omits
`"structural"`, including its remedy and response fields, see the [proof endpoint
reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs).

To localize witnesses by a caller-known business key, pass `row_identity` as a
source-coordinate object map, for example `{"PUBLIC.ORDERS": ["ORDER_ID"]}`.
Each key position may also be a `{"coalesce": ["col_a", "col_b", ...]}` term
when the first non-NULL value across those columns is the business key; use the
API reference for the complete grammar and per-side form. See that reference for
`concat` row-identity terms.
The proof admits the run first; its comparison probes each declared key on both sides.
An unusable key refuses the pair during that comparison rather than returning a
submit-time `400`. Omit `row_identity` to use only the engine-declared basis; see the
[proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs)
for validation and evidence fields.

`prove` has no separate `target_model` argument: its behavior comes from the sealed
`spec_hash`. See [Declared Data Vault target shapes](/docs/Genesis-Prover/Overview#declared-data-vault-target-shapes)
for the comparison rules and the [proof API reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs)
for the sealed-artifact contract. A version-2 model can declare computed `derived` targets;
the comparison checks their presence and declared columns without comparing their rows to
one source table. A legacy source used only to build a derived target is expected to be
absent under its own name on the target side; see the [target-model rules](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes)
for the same-name layer exception. If the target is vault-shaped, or objects are unpaired
on both sides, but the sealed spec omitted the model, the run summary instead carries
`undeclared_target_shape` guidance. Read the guidance, complete the model from the mapping
document, reseal the spec, and run `prove` again; when nothing paired, the resulting review
population is not approvable.
When `comparison_counts.comparisons_matched` is the integer `0` (not absent, null, boolean,
or negative), the proof report says that no objects matched before it presents the grade.
The grade may still contain an obligation tally; that tally does not mean values were compared.

For late-completion and terminal-attribution details, use `get_run(prover_run_id=run_id)`
and read [How a Run Works](/docs/Genesis-Prover/How-A-Run-Works#terminal-error-attribution)
alongside the [run API reference](/docs/Genesis-API/API-Reference#estate-source-contract-endpoints).

The [Prover workflow guide](/docs/Genesis-Prover/Agents-And-The-API#one-trigger-the-proof)
explains how addressing is recorded when proofs are repeated.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_snapshot_id` | string | `""` | Characterization snapshot for the source estate. Give this or `source_boundary_hash`; a snapshot id wins when both are given. |
| `target_snapshot_id` | string | `""` | Characterization snapshot for the target estate. Give this or `target_boundary_hash`. |
| `source_boundary_hash` | string | `""` | Names the source side by its boundary instead of by an exact snapshot; the latest snapshot of that boundary is taken. |
| `target_boundary_hash` | string | `""` | Names the target side by its boundary; the latest snapshot of it is taken. This is the one a repair round wants — the target's snapshot id changes every round and its boundary does not. |
| `spec_hash` | string | `""` | Optional 64-hex hash addressed by `read_spec`; attaches a sealed spec for grading. |
| `source_connection_id` | string | `""` | Used with `spec_hash`; omitted, defaults to the connection recorded for the sealed spec's authoring seat. If the record has none, pass a registered source connection in `<type>.<name>` form. |
| `target_connection_id` | string | `""` | Used with `spec_hash`; omitted, defaults to the seat's recorded `target_connection_id`, or its own connection when the seat was commissioned with `source_catalog` or `target_catalog`. If neither is recorded, pass a registered target connection in `<type>.<name>` form. |
| `schema_map` | object | `null` | Optional source-to-target schema mapping for whole-schema relocations, such as `{"MAIN": "DAILY_ANALYTICS"}`. A source table declared input-only by the target model does not need an entry solely because the build loads it into no target object. A source table declared unassessed is also paired with nothing and does not need an entry; see [declared target mappings](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes). |
| `object_map` | object | `null` | Optional per-object rename mapping, keyed and valued as `schema.object`. Renames only: a null or empty target is refused. Declare an input-only table through the sealed spec's target model when calling `prove`; do not use a null mapping value. |
| `column_map` | object | `null` | Optional caller-declared column renames, keyed by source object in source coordinates like `object_map`, with exact `{source_column: target_column}` names; for example, `{"MAIN.FLIGHTS": {"flight_id": "flightId"}}`. The target column is looked for on that object's image after the delta's object move and schema/object maps. A declared rename pairs the columns and compares their content; without one, the columns remain missing and surplus. For resolution and refusal details, see [`column_map` in the proof API](/docs/Genesis-API/API-Reference#post-api-estate-proofs). |
| `invariant_side` | string | `"source"` | Which estate an INVARIANT obligation is graded against, with `spec_hash`: `"source"` or `"target"`. An invariant is a single-relation column-domain assertion, so it grades wholly on ONE side; pass `"target"` when the spec asserts about the estate being BUILT. This is the FALLBACK: an obligation that declares its own `invariant_side` grades on the side it declares. Keyed obligations always compare source against target. Ignored without `spec_hash`. |
| `source_catalog` | string | `""` | Catalog the SOURCE side's `SCHEMA.TABLE` names resolve in, bound as the session catalog for the grade's source reads. Requires `spec_hash`. Omitted, it defaults to the database the source snapshot characterized when the engine binds a catalog (Databricks, Snowflake); otherwise the connection's default. |
| `target_catalog` | string | `""` | Catalog the TARGET side's `SCHEMA.TABLE` names resolve in, target-side invariants included. Requires `spec_hash`. Omitted, it defaults to the database the target snapshot characterized when the engine binds a catalog; otherwise the connection's default. |
| `row_identity` | object | `null` | Optional caller-declared row identity in source coordinates: map each schema-qualified source object to one or more key terms, such as `{"PUBLIC.ORDERS": ["ORDER_ID"]}`. A position may be `{"coalesce": ["col_a", "col_b", ...]}` to use the first non-NULL value across at least two distinct columns, or `{"concat": [<part>, <part>, ...], "sep": "<text>"}` to join two or more parts into one position when a target key was built from several source columns. Concat parts may be columns or coalesce terms; text, integer, exact decimal, date, and UUID parts are supported, and a NULL part makes the key NULL. Composite keys are positional. The comparison probes each key on both sides; a non-unique, NULL-bearing, missing, or unresolvable key refuses the pair. If the sealed target model declares the source object as a split, a row key on that legacy object is refused because it has no single target image; see [declared target mappings](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes) for the derived-target rule and refusal details. If the probe cannot read one side as the submitting identity, the refusal reports that declaration in the proof's `summary.unverifiable_objects` with its side and cause and keeps it in the remedial call; see the [proof request contract](/docs/Genesis-API/API-Reference#post-api-estate-proofs). Omit it to use only the engine-declared basis. |
| `case_insensitive_object_names` | boolean | `null` | Optional. Pair objects whose names differ only in case. A cross-engine migration needs it WHEN the two engines spell object names in different cases, or `Dimension.City` and `DIMENSION.CITY` pair with nothing and the whole target reads missing. Where the casing already matches, leave it off: pairing case-insensitively can join two names a case-sensitive deployment treats as distinct objects. Omit for the deployment's configured default. |
| `change_expectation` | string | `null` | Optional. The migration's shape in one word when there is no spec: `must_match` for a lift-and-shift (any difference is the finding) or `must_differ` for a change (with no spec it licenses nothing, since nothing says which differences are intended). Recorded on the proof as the caller's declaration, attributed to the calling identity. With `spec_hash` it must restate the spec's own shape, or the submit is refused. |
| `title` | string | `""` | Required. The comparison's business title, the headline a person reads it by in Human Review and on the comparisons grid, in the form `<Business subject>: <source role> → <target role> (<spec name or 'no spec'>)` — for example `Foundry aviation: raw → ontology rebuild (spec-mediated)`. Name what each side is, not its estate or connection id. A missing or blank title is refused with `refusal.suggested_title`, a suggestion built from the two sides and the spec. `compare` and `grade` take it too. For no-spec `prove` and `compare` titles, see the [API title rule](/docs/Genesis-API/API-Reference#post-api-estate-system-diffs). |
| `estate_id` | string | `""` | Optional named estate id for run provenance and review-theater routing. |
| `round_n` | integer | `null` | Optional repair-round label. Omit it when no repair loop exists; repeated proofs for the same round are idempotent while the pair's licensing is unchanged. If its correspondence-rule bindings change, the proof is recomputed; see the [proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs). |
| `wait_seconds` | integer | `0` | Optional non-negative inline wait. Use `0` to submit and be told when the run is terminal — or, with `notify=false`, to poll `get_run(prover_run_id=run_id)`. |
| `notify` | boolean | `true` | Queue a wake for this thread when the run is terminal, carrying the same handle a poll returns: it arrives on your next tool result if you are mid-turn, or as a new turn once you are idle. While armed, the handle's `next` says so instead of asking you to poll. Set `false` only to check on the run yourself. |

Catalog resolution and grade idempotency are defined in the [compiled-grade API
reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled).

Example:

```python theme={null}
prove(
    source_snapshot_id="snapshot_source",
    target_snapshot_id="snapshot_target",
    spec_hash="<sealed-spec-hash>",
    source_connection_id="snowflake.source",
    target_connection_id="snowflake.target",
    schema_map={"MAIN": "DAILY_ANALYTICS"},
    row_identity={"PUBLIC.ORDERS": ["ORDER_ID"]},
    title="Daily orders: MAIN source → DAILY_ANALYTICS rebuild (spec daily_orders)",
)
```

A relocation task is expressed with `schema_map` and `object_map` — the mappings above —
not with a declared-relations premise. The `prove` VERB does not accept one: it refuses an
unrecognised argument by name rather than ignoring it, so a call passing
`declared_relations` gets `refusal.kind: "invalid"` and nothing runs. The same is true of
`tiers`: the verb always grades every gradeable tier, because a tier subset is a different
measurement and narrowing it silently on an agent path is not a default worth having. Both
are properties of the proof ENDPOINT's request model; see the
[proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs) for them
and for the premise lookup window.

For a cross-engine relocation whose engines spell object names in different
cases, pass `case_insensitive_object_names=true` as well, or objects whose names
differ only in case pair with nothing and the whole target reads missing.

The response includes `run_id`, `status`, the common run `envelope`, and `wait`.
The envelope links to `get_run`; its summary names `comparison_run_id` and,
when a spec was attached, `grade_run_id`, and preserves the proof's
`source_snapshot_id` and `target_snapshot_id`. Terminal `refused` means the system
declined the request (for example, a seal did not verify or a connection was not
registered), not that the run crashed. See the [proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs)
for the full REST request and response contract.

For graded-proof regression fields and the effect of an unmeasured tier, see the
[proof endpoint reference](/docs/Genesis-API/API-Reference#post-api-estate-proofs) and
[what certifies](/docs/Genesis-Prover/Agents-And-The-API#what-certifies-means).

### `propose_correspondence_rules`

Seed and edge-qualify the default platform-correspondence (`Π`) rule pack for an
engine pair. A pack is available only for supported pairs; use
`propose_rename_correspondence` for renamed objects or schemas, and
`triage_unlicensed_findings` for residuals discovered by a comparison. Seeding and
qualification make the rules eligible but do not ratify or license them. Pass the
characterization snapshot ids when available so qualification is bound to the pair's
environment.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `component_pair` | string | required | Engine pair in `<source>-><target>` form, for example `mssql->databricks`. |
| `source_snapshot_id` | string | `""` | Optional source characterization snapshot used during qualification. |
| `target_snapshot_id` | string | `""` | Optional target characterization snapshot used during qualification. |
| `diff_hash` | string | `""` | Optional stored comparison hash used to build the human ratification hand-off. |
| `availability_only` | boolean | `false` | When `true`, returns the pair's pack counts (`shipped_count`, `proposed_count`, `unproposed_count`, `built_in_count`) and writes nothing. |

Use `availability_only=true` to find out whether a pair ships a pack: a plain call
seeds the whole pack into the human ratification worklist. The counts are the same ones
`GET /api/estate/correspondence-rules/pack-availability` returns.
For legacy copies, Genesis also reseeds the pinned pack edition at backend startup; see
[Genesis Prover](/docs/Genesis-Prover/Overview) for how that affects the rule worklist.

The response returns the qualified rules and any `ratification_url`, `actionable`, and
`blocked_by` hand-off fields. Each rule includes `proposed_by`, the author recorded on
its content-addressed row, and the response includes `attributed_to_another`: `true`
when any rule names another person, `false` when all rules name the caller, and `null`
when a rule names nobody. Re-seeding an existing pack returns its first recorded
authors rather than attributing the rules to the caller; an unnamed author is shown as
`"unattributed"`. The operation writes and qualifies the pack, but takes no extra
author read because the workflow returns the recorded authors with the rules.

### `grade`

Re-grade a new sealed specification against an existing comparison without taking new
estate characterizations. This also covers a migration whose tables were already landed
and compared before anyone wrote down its specification: author and seal the migration's
requirements, then use `grade` to measure those obligations against the live estates.
Use it for a repair round when the characterized estate and comparison are unchanged.
Before a comparison exists, you can grade the spec's obligations alone against the two
live connections with `tiers=["derivational"]`; this needs no snapshot pair. When you
also need the estates compared and the structural tier graded, use `prove(spec_hash=...)`
for the first comparison, or re-characterize and prove again after target configuration
changes. See [how grading rounds stay
repeatable](/docs/Genesis-Prover/How-A-Run-Works#grading-is-separately-repeatable).
Every grade call also requires `title`, the business name shown for the comparison in
Human Review and on the Prover landing. As with `prove`, a missing or blank title is
refused with a suggested value; the `prove` parameter table describes its format.
When the sealed spec declares a target model but the named comparison was made without
it, this tool compares the pair again under the model before grading and records that
replacement in the run provenance; the operation therefore performs a second full
comparison. It carries the comparison's recorded `row_identity_declared`; a key that
does not pair rows under the model is reported as indeterminate, not guessed. See [when a
grade names a comparison made without its spec](/docs/Genesis-Prover/Overview#when-a-grade-names-a-comparison-made-without-its-spec)
for the reason recorded on the grade and the rule that controls whether the replacement
comparison inherits its title.
If a failing grade read no comparison, follow its returned `next` call: it points to
`prove` for a single spec or to a SET re-grade with `spec_hashes` and the structural tier;
see [how the Prover routes comparison-less grade failures](/docs/Genesis-Prover/Agents-And-The-API#prover-run-progress).
Omit `source_connection_id` and `target_connection_id` to use the source and target
connections resolved from the seals when every member agrees. For a reseal with no recorded
connection, resolution follows its parent seals to the nearest recorded connection; see the
[`load_prior_spec` repair binding rules](#load_prior_spec). If a seal still does not resolve
a connection, provide its registered connection explicitly. A named source that differs from
a member's sealed source is refused; a named target is refused only when that member's seat recorded a
commissioned target connection. A target inferred from catalog placement on the source is
not a recorded target, so it does not prevent grading a migration on another connection.
If a set's seals record different connections, no single call can grade all its members;
grade each separately with `spec_hash` on its own sealed connections. The refusal names
the conflicting connections and directs you to the applicable retry. For a single
connection mismatch, the proposed grade call preserves the other non-default grade
arguments you supplied and substitutes the seal-recorded connection; use it rather than
rebuilding the request.

The tool claims the round and returns a run handle immediately. Poll
`get_run(prover_run_id=run_id)` until the status is terminal, or set `wait_seconds` to
wait inline first. An expired wait never stops the grade. While the grade is running,
`data` includes `request_key`, `tiers_graded`, and `pending_basis`, but does not include
`findings` or `obligations` because those results do not exist until measurement finishes.
Read the verdict summary, obligation results, and durable `#N` finding ids from the
finished run. An identical finished request returns its complete verdict with
`data.reused: true`; a round already in progress is refused with `kind: "conflict"`.
The request identity includes the running grading-code version, so repeating a request
after the grader changes grades it again instead of returning the retired grader's
verdict. On a reused response, `data.reused_from_grade_version` identifies the grading
code recorded by the run that supplied the answer; it is `null` when the grade ran or
the reused run recorded no version.
If the seal cites a retired clarification (overturned by a person or withdrawn by its
recording agent), the tool refuses admission; see [how a run handles reopened
seals](/docs/Genesis-Prover/How-A-Run-Works#grading-is-separately-repeatable) for the
required reseal path.
When an unlicensed obligation fails, the completed verdict also carries
`failed_checks`, with the obligation id, available mismatch and row counts, up to three
sample keys, and a rendered sentence. For a failure over a column missing from the
target, the entry instead has a null `mismatched_key_count`, plus
`missing_target_columns` and `unchecked_source_rows`; see [how failed checks are
surfaced](/docs/Genesis-Prover/Overview#3-spec-conformance-the-spec-agent-and-the-grade)
for how that unlocalized failure is reported.
The overview also explains how a membership difference with keys on both sides is
worded and when its examples identify the side for each key.
For a keyed obligation left unmeasured because its key is duplicated only on the target,
the grade records a decided `fail` rather than `unverified`. It does not make that
conversion when the degeneracy probe measured the expected side empty; an empty expected
population has no key to duplicate. For how refused key comparisons are sized in the
failed-check headline, see [failed checks in the grade overview](/docs/Genesis-Prover/Overview#3-spec-conformance-the-spec-agent-and-the-grade).
For how `report_this` points to failures beyond its named-check limit, see
[reporting a completed run](/docs/Genesis-Prover/Agents-And-The-API#reporting-a-completed-run).
The Prover turns the same failures into Human Review blockers. If the grade read no
comparison, those blockers appear on the grade's own proofless review; that review can
take rulings and exceptions but cannot be approved. Use its returned `next` call to
run `prove` or the required SET re-grade so a comparison-backed review can be approved.
For a finished grade that read no comparison, both the `grade` result and a `get_run`
poll carry `data.review_url`, `data.review_url_basis`, and `data.review_path` for that
grade's review, with `review_path` present in every case. `review_url_basis` begins with
`addressed_grade` when the deployment's public address is available; it can also begin with
`addressed_conversation` or `addressed_local` when a fallback address is used. If neither
fallback is available, it begins with `no_public_base_url` or `address_unreadable`; use
`review_path` to open the page in the Genesis dashboard when `review_url` is null. The
basis values are described above.
Use the [grade response reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled)
for returned fork fields.
For the declared coordinate on conformance drift findings, see [Drift findings declare
their coordinate](/docs/Genesis-Prover/Agents-And-The-API#drift-findings-declare-their-coordinate).

When this production grade becomes the comparison's review over a previously approved
review population, the finished response includes `data.approval_superseded`. It names
the recorded decision, approver, approval run, superseding grade run, and a sentence that
the approval no longer binds and the comparison is awaiting review again. A `null` value
means this grade superseded no approval. The same disclosure is promoted on the run
envelope and review surfaces; see [when a re-grade changes approval truth](/docs/Genesis-Prover/How-A-Run-Works#when-a-re-grade-changes-approval-truth).

A finished grade returns `not_compared_by_design`, `derived_checked`,
`derived_unchecked`, `derived_unchecked_reasons`, and `row_checked` alongside its verdict counts.
`row_checked` names `same` scope objects verified by passing row checks because their
whole-table digest cannot be compared across engines; the grade headline says they were
verified by row checks, not by digest.
The first is the number of design-skipped split-image digests; the two lists identify
derived targets whose skipped digest is cleared by sealed coverage or remains in the
blocking `indeterminate` results, respectively. A covering check that passes but measures
degenerate expected-side data (empty, all-`NULL`, or all-zero) confirms nothing, but does
not undo confirmation from another passing, non-degenerate check. A failed or unverified
covering check prevents confirmation. `derived_unchecked_reasons` maps each unchecked
target read by a check to the reason: a covering check did not pass, or its only covering
checks passed but measured degenerate. Targets with no covering check have no reason entry.
See [declared target mappings](/docs/Genesis-Prover/Overview#declared-target-mappings-and-data-vault-shapes)
for the comparison rule. The `report_this` line also counts `derived_checked` tables as not
compared cell by cell; see [reporting a completed run](/docs/Genesis-Prover/Agents-And-The-API#reporting-a-completed-run).
The grade summary also returns `scope_unaccounted_columns`, `scope_unaccounted_limits`, and
`scope_unaccounted_readings`; the first names new target columns awaiting a person's
decision, the second discloses limits on the source columns used to make that reading, and
the third lists the exact unlicensed readings held for that decision.
See \[scope verdicts]
(/docs/Genesis-Prover/Agents-And-The-API#scope-verdicts) for how these affect the grade and
Human Review.

When a carried scope entry is unpaired for want of a `schema_map`, the summary's
`schema_map_unpaired` block groups the source and target objects attributed to that cause;
the grade and review population state the missing map once rather than counting each entry
and target object again. See \[scope verdicts]
(/docs/Genesis-Prover/Agents-And-The-API#scope-verdicts) for the fields and grading semantics.

For the grade's explicit distinction between failed and unmeasured items, and the
nullable derived-split fields, see the [grade response reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled).

For how the grade treats target objects outside the declared scope, see
[scope verdicts](/docs/Genesis-Prover/Agents-And-The-API#scope-verdicts).

A finished grade, including one returned by `prove` with a spec, can also end a check as
`nothing_to_check`, rendered `Nothing to check (0 rows)`. Report it as a measured empty
population, not a pass, failure, error, or skipped check; use the grade headline to say
whether the other checks verify the claim. See [how a grade reports an empty check](/docs/Genesis-Prover/Agents-And-The-API#when-a-grade-did-not-measure).

For example, grade obligations before a comparison exists:

```python theme={null}
grade(
    spec_hash="<sealed-spec-hash>",
    source_connection_id="<source-connection>",
    target_connection_id="<target-connection>",
    tiers=["derivational"],
    title="Orders: legacy warehouse → new warehouse obligations (spec orders)",
)
```

For selected-check grading, pass `check_ids` to `grade`; the [API reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled)
defines the partial-result contract and refusal conditions.

```python theme={null}
grade(
    spec_hash="<sealed-spec-hash>",
    source_connection_id="<source-connection>",
    target_connection_id="<target-connection>",
    check_ids=["O3", "O7", "O9"],
    title="Orders: selected obligation checks (spec orders)",
)
```

The finished run envelope publishes obligation totals in `summary.obligation_counts`,
including on a derivational-only grade. Its top-level `items` are structural spec items,
not the obligations measured, so an empty list does not mean the grade checked nothing;
see the [grade response reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled)
for the count fields and obligation-record paths.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `spec_hash` | string or null | `""` | Sealed compiled-spec hash for a single-spec grade. Supply this **or** `spec_hashes`, never both. |
| `spec_hashes` | string\[] | `[]` | Two or more sealed compiled-spec hashes to grade as one result. A set grade reports ownership, overlaps, conflicts, and only uncovered columns as drift. Supply this **or** `spec_hash`, never both. |
| `title` | string | `""` | Required business title shown on the comparison in Human Review and on the Prover landing. Omitted or blank is refused with `refusal.suggested_title`; see the `prove` parameter table for its format. |
| `source_connection_id` | string | `""` | Registered source connection. Omit to use the source recorded by the seals when all members agree; supply it when a seal has no source record. A supplied source that contradicts any member's recorded source is refused. |
| `target_connection_id` | string | `""` | Registered target connection. Omit to use the target resolved from the seals when all members agree; supply it when a seal cannot resolve a target. A supplied target that contradicts a commissioned target recorded by any member's seal is refused. A target inferred from catalog placement is not treated as a recorded target. |
| `diff_hash` | string | `""` | Optional persisted comparison id; omit to resolve the comparison from the snapshot pair. |
| `source_snapshot_id` | string | `""` | Required when the structural tier is graded. |
| `target_snapshot_id` | string | `""` | Required when the structural tier is graded. |
| `invariant_side` | string | `"source"` | Which side supplies the invariant reference: `source` or `target`. |
| `source_catalog` | string | `""` | Catalog the source side resolves in. Omitted, it defaults to the database the source snapshot characterized when the engine binds a catalog (Databricks, Snowflake); otherwise the connection's default. On a known one-database-per-connection engine, naming that characterized database is equivalent to leaving the catalog unbound. |
| `target_catalog` | string | `""` | Catalog the target side resolves in, target-side invariants included. Omitted, it defaults to the database the target snapshot characterized when the engine binds a catalog; otherwise the connection's default. Name both when one connection serves both estates as two catalogs and no snapshot is named. On a known one-database-per-connection engine, the target invariant can use the connection's database without `target_catalog`; naming that characterized database has the same effect. |
| `estate_id` | string | `""` | Optional named-estate id for review-theater routing. |
| `round_n` | integer | `0` | Repair-round label used in the grade request identity. |
| `estate_coordinate` | string | `""` | Optional estate measurement coordinate used in the grade request identity; see [how grading rounds stay repeatable](/docs/Genesis-Prover/How-A-Run-Works#grading-is-separately-repeatable). |
| `tiers` | string\[] or null | `null` | Tiers to grade; omit for every gradeable tier, or for `["derivational"]` when `check_ids` is supplied. A derivational-only grade needs no snapshot pair and mints no structural findings. |
| `check_ids` | string\[] or null | `null` | Grade only these sealed check (obligation) ids. Supply at least one id; an unknown id is refused with the valid ids. This partial grade reads no comparison, so it cannot include `structural` or `diff_hash`. Omit to grade every check. |
| `wait_seconds` | integer | `0` | Optional non-negative inline wait before returning the run handle. Use `0` to submit and be told when the run is terminal — or, with `notify=false`, to poll `get_run`. |
| `notify` | boolean | `true` | Queue a wake for this thread when the run is terminal, carrying the same handle a poll returns: it arrives on your next tool result if you are mid-turn, or as a new turn once you are idle. While armed, the handle's `next` says so instead of asking you to poll. Set `false` only to check on the run yourself. |

If a declared key is read but rejected as non-unique, inspect the refusal's remedial
arguments before dropping it. A different usable form may add columns that distinguish
repeated rows, use a first-non-NULL key such as
`{"coalesce": ["adjusted_number", "original_number"]}`, or declare different key
columns for each side with `{"source": [<key terms>], "target": [<key terms>]}`.
The backward comparison re-keys those per-side probes to its own source and target
roles; flat keys remain unchanged.

Example:

```python theme={null}
grade(
    spec_hash="<new-sealed-spec-hash>",
    source_connection_id="snowflake.source",
    target_connection_id="databricks.target",
    diff_hash="comparison_123",
    source_snapshot_id="snapshot_source",
    target_snapshot_id="snapshot_target",
    round_n=2,
    estate_coordinate="<estate-coordinate>",
    title="Orders: Snowflake source → Databricks rebuild, round 2 (spec orders v2)",
    wait_seconds=0,
)
```

The tool requires `ratify_source_contract`. The minutes of warehouse work run behind
the handle whether or not anyone continues polling.

Finished grades expose the structural and live-read intervals plus `vintage_basis`,
and on a `blended` grade `vintage_between_reads`, which says whether either estate's
write history shows a write between the two reads. Relay the envelope's `vintage_caveat`
beside the verdict; its wording and the limits of `not_confirmable` are described in
[how a run reports observation vintage](/docs/Genesis-Prover/How-A-Run-Works#grading-is-separately-repeatable)
and the [grade response reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled)
for how to interpret them. For a set grade, every member's obligations run, the response
returns the set identity in `spec_hash` plus sorted `spec_hashes`, and the completed run
view carries `spec_set` ownership, overlaps, and conflicts. When the structural tier was
graded, `data.summary.spec_set_reading` also relays those members, their seals, conflicts,
overlaps, and uncovered differences in the review card's wording; see the [API response
reference](/docs/Genesis-API/API-Reference#post-api-estate-spec-conformance-grade-compiled)
for its fields.

Adjudication proceedings use the packaged constitution only when its content
matches the build's integrity pin. For the current `v4` constitution, the
expected SHA-256 is
`7464dc71d2c0d65f8c6abbcde42b6dc2eba4d241cea415afe76776d0f98763fc`. A digest
mismatch raises `ConstitutionPinError` and fails closed before the proceeding is
opened, rather than recording an unverified constitution as provenance. Open
proceedings continue to resolve the immutable constitution version and digest
recorded when they started, even after a newer constitution is pinned.

### `request_consult_ruling`

Ask the built-in **Prover Consult** agent to measure one reason not to fix an open
finding rather than arguing about it. The caller supplies the finding number, one
dispute shape, and the implementer's position; Consult hydrates the finding's
rationale, compiled readings, computed values, check SQL, two databases, and ticket
from the ledger. The tool is available to agents carrying `source_contract_tools`.

Consult returns `ACCEPTED_SUPPORTING`, `REJECTED`, `ESCALATE`, or
`INVALID_DOCKET`, together with its read-only probes and any mechanical guard. It
uses one full bot turn and read-only `SELECT` probes, so call it deliberately and
only once per dispute at a time. A second call on the same finding is an appeal;
the service continues the same thread and allows at most three rounds for the same
measurement. This tool opens no review item and does not itself close or license the
finding. For an `ACCEPTED_SUPPORTING` ruling, a person asks for approval from the finding;
the decision is made through Action Review. See [Prover roles and approvals](/docs/Genesis-Prover/Roles-And-Approvals)
for which rulings use that route and what approval changes. The decision must use the
ruling's exact `ruling_digest_id`, so a ruling made obsolete by a later Consult round
cannot be applied accidentally.

Consult performs the provider readiness check before creating its thread, so a
provider failure spends no round; follow the returned `cause` and remedy rather
than retrying in a loop. The check uses the shared
[`llm.provider_preflight_ttl_seconds`](/docs/Setup/Advanced-Settings#llm-streaming-timeouts)
window.

When a finding is one leg of a declared fork, the docket includes the fork axis and
the compiled readings for that axis. If the same leg's grade changes between the
earliest and latest graded sightings while the finding remains open, the docket marks
the axis as moved and lists the direction of each measured change. In that case no
probe against the current build can establish which reading the ticket requires: the
build now embodies one of the readings, so re-running either leg only reproduces its
current state. An `ACCEPTED_SUPPORTING` ruling is therefore escalated rather than
licensed, with the implementer's values standing for human review. The docket tells
the agent to use the ticket wording to identify the required reading, or record a
specification flag when the ticket does not decide the fork.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `finding_id` | integer | none | Required durable finding number (`#N`). The finding must be open; its contents are read from the ledger. |
| `dispute_kind` | string | none | Required dispute shape: `explanation`, `reading`, or `check_defect`. |
| `implementer_position` | string | none | Required reason in the caller's own words, stating the rule or ticket reading being defended. |
| `finding_sha` | string | none | Optional content hash from an earlier call. It pins the finding's version but is not its identity: the ruling is bound to the complete finding reference (ledger, durable finding number, and version). If the finding was re-measured, the call is refused as `finding_changed` instead of disputing obsolete values. |

The response includes `rounds_remaining`, the number of consult rounds the same
finding revision can still use. It reflects the durable ruling history rather than
the returned `round_number`: `INVALID_DOCKET` and an `ACCEPTED_SUPPORTING` result
without a valid probe do not spend a round. If the finding changes, is resolved, or
cannot be read while Consult is working, the ruling is returned but not recorded
against that obsolete revision; `rounds_remaining` then describes the current
revision (or is `null` when its budget cannot be read).

Example:

```python theme={null}
request_consult_ruling(
    finding_id=42,
    dispute_kind="explanation",
    implementer_position=(
        "The ticket requires the stored null representation to remain distinct, "
        "so the differing null count is licensed by the requirement."
    ),
)
```

An accepted ruling is recorded on the finding. See [Prover Consult Agent](/docs/Genesis-Data-Agents/Prover-Consult-Agent),
[Advanced Settings](/docs/Setup/Advanced-Settings#prover-consult-ruling-application-estate_char.consult)
for its board effects and `estate_char.consult.apply_mode` configuration, and the [Estate
API reference](/docs/Genesis-API/API-Reference#consult-ruling-on-a-finding) for the
read, approve, and decline endpoints.

### Builder-facing fix brief

Each reconciliation round renders a builder-facing fix brief from the product's
episode records. It includes the ticket text, open findings with their rationale,
readings, evidence, computed expected-versus-stored values, and the source/target
SQL behind the check when available. It also includes perimeter questions for
estate changes that are not claimed by the ticket.

The brief keeps operator-provided ticket text and product-generated finding fields
verbatim, including ordinary words such as `score` or score-bearing column names;
those inputs are not oracle disclosures. Verdict language composed by the gate is
still refused, and the refusal identifies the bounded offending line so the source
can be repaired without guessing which finding triggered it.

When an item comes from one leg of a fork, the brief labels it as a fork leg instead
of presenting that reading as a settled expected value. It shows the fork axis, the
reading bound to the item, and every other compiled reading for the same sentence
with that check's recorded standing: satisfied, not satisfied, or not measured. This
context is included so a builder does not change a check that currently satisfies a
rival reading without knowing that the specification has not settled the choice.
For a finding whose record carries several readings but cannot identify its bound
leg, the source SQL is likewise described as the result of one reading rather than
as the expected value.

For persisted conformance re-grades, an issue is closed by absence only when the
round's `tiers_graded` coverage includes its category: `structural` covers both
`structural` and `drift`, while `derivational` covers `derivational`. Issues in
ungraded categories remain open for a later round; see the [episode rounds API
reference](/docs/Genesis-API/API-Reference#post-api-estate-episodes-episode-id-rounds).

Findings are grouped by their recorded state. `open` findings ask the builder to
make a change; findings closed by an independent ruling are delivered for context
but marked `[NO ACTION REQUIRED — information, not a fix request]`; and
`escalated` disagreements are delivered with the builder's stored values standing
while they wait for a human ruling. The brief uses the durable finding reference
(for example, `#42`) for replies; compiled obligation IDs are supporting detail,
not reply IDs.

The brief states what the round asks separately from how many findings it contains.
On the ordinary `finding` level, the durable finding references are the requested
work. On the `ticket` level, the ticket's opening words state the work because the
product could not attribute any observed item to the build; those items appear under
an unowned disclosure section with their location, observation, and reason no durable
item ID exists. They are not dismissed as acceptable, and they do not receive reply
IDs. Perimeter questions remain separately answerable with their `PQ-n` references.

The brief ends with the reply protocol. Reply on its own line for each open item:

```text theme={null}
FIX #42
EXPLAIN #42: the stored value follows the ticket's rule
CHECK-DEFECT #42: the check compares different grains
```

Use `FIX` after rebuilding the artifact, `EXPLAIN` when the artifact is correct as
built, or `CHECK-DEFECT` when the check itself is malformed. Unanswered open items
remain open. Items marked as requiring no action do not need a reply. The brief is
oracle-blind: it does not tell the builder whether the build passed or failed.

For a sealed-spec conformance run, use `get_conformance_fix_brief` after the
Adjudicator completes instead. That variant hands the builder only the cited
rules for `target_defect` verdicts, without suite grading numbers or adjudication
receipts.

### `triage_unlicensed_findings`

Analyze the unlicensed residual from a stored system comparison and draft
proposals for differences that may be safe platform representation quirks. This
tool is read-only by default and never approves or ratifies anything. Set
`register_proposals` to `true` only when the human operator asks to file the
proposals; they remain unlicensed until they pass the qualification and human
ratification workflow.

For `column_null_count` findings, the tool can propose a `null_form_equivalence`
rule only for a text column whose measured categorical value-count map
corroborates that one engine writes absent values as SQL `NULL` and the other as
the empty string over the same rows. A difference where both sides have
different non-zero null counts, a non-text column, or a column without the
required map is left for review or unclassified rather than proposed. The
proposal includes the affected columns as `null_form_columns` and edge fixtures;
the comparison still keeps each column's content digest, distinct-count, and
categorical-map verdicts separate.

The response includes exact `counts`, `proposed_pi_rules`, `needs_review`, and
`unclassified` buckets. Each
bucket is returned with at most `sample_limit` example entries (default `25`);
counts remain exact, and a truncated bucket is marked with its corresponding
`*_truncated` field. Use this before ratification to turn a raw residual into a
reasoned proposal, then use the ratification tools for the human approval step.
When `register_proposals=true`, each returned item in `proposed_pi_rules` also has
`proposed_by`, the author recorded on that rule's durable row, and the response has
`attributed_to_another`. The latter is `true` if any registered rule names someone
else, `false` if all name the current caller, and `null` when no rule was registered
or a rule names nobody; an unnamed author is returned as `"unattributed"`. A
content-addressed rule keeps its first recorded author when another caller registers
the same proposal. Draft mode writes no rule and therefore returns no attribution
verdict. Before registration, every proposal's `rule_id` must match the content hash
of its definition; if any id does not match or a definition cannot be read as a rule,
the call refuses the registration before storing any proposal.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Required content hash of the stored mediated diff to triage, returned by `run_system_diff`. |
| `register_proposals` | boolean | `false` | When `true`, store the generated proposals with status `proposed` so they appear in the ratifications worklist. Registration still licenses nothing. |
| `sample_limit` | integer | `25` | Maximum number of example entries rendered per bucket. Values less than `1` are clamped to `1`; counts are always exact. |

### `list_finding_dispositions`

Read the per-finding diagnosis state before proposing or correcting a package.
Use it to see which findings are undiagnosed, what verdict was recorded, the
grounds for that verdict, and who recorded or proposed it. The response includes
one row per matching finding, `total`, `by_disposition` counts for the filtered
set, and paging metadata. This call changes nothing.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | `null` | Restrict to findings most recently exhibited by one system comparison. |
| `component_pair` | string | `null` | Restrict to one engine pair. |
| `disposition` | string | `null` | A recorded diagnosis, or `undiagnosed` for findings with no diagnosis. |
| `comparison` | string | `null` | Restrict to one comparison class. |
| `object_name` | string | `null` | Restrict to one object. |
| `status` | string | `open` | `open`, `closed`, or `all`. |
| `offset` | integer | `0` | Skip matching findings; the tool applies its bounded page size. |

Call this before `propose_finding_disposition_package` or
`propose_finding_disposition_correction`. A named diagnosis can be inspected
through `disposition_note`, `dispositioned_by`, and
`disposition_proposed_by`; the model-scoped ruling field is documented in the [Estate
API reference](/docs/Genesis-API/API-Reference#get-api-estate-findings-dispositions).
No evidence document is returned by this focused read. Results are scoped to the
person the agent is working for: findings from comparisons they cannot see are removed
before `findings`, `total`, and `by_disposition` are calculated. A `diff_hash` they
cannot open is answered as unknown. The visibility check costs one scope load (four
index reads) before the ledger read.

### `disposition_system_diff_finding`

Send one system-diff finding back to be fixed by recording `target_defect`
directly. A send-back needs no approval and leaves the finding open until a fresh
comparison shows the fix; the tool does not file a remediation request or hand
work to a builder. It refuses a finding already diagnosed with another disposition,
and it refuses findings the Adjudicator left as `question` or `spec_ambiguity` until
the owner answers. Other diagnoses settle a difference without a fix and require a
human-approved package; use
`propose_finding_disposition_package` (or
`propose_finding_disposition_correction` to replace a recorded diagnosis). On
success, the response includes `success`, `finding_key`, `disposition`,
`dispositioned_by`, `already_sent_back`, and `open_package_items`. The actor is the
signed-in user when present, otherwise `agent:<bot_id>` when the turn has an acting
bot, or the repository's non-human marker when neither identity is available.
`open_package_items` identifies open packages made stale by the send-back; notify
their proposers. A refusal writes no disposition and returns no actor. Legacy
send-backs staged in open initial packages are also handled at startup; see the
[Prover package approval guidance](/docs/Genesis-Prover/Roles-And-Approvals#approve-a-disposition-package).

| Parameter | Type | Default | Description |
| - | - | - | - |
| `finding_key` | string | none | Finding to diagnose. |
| `disposition` | string | none | Must be `target_defect`; every other disposition is refused because it settles the difference without requiring a fix. |
| `note` | string | `null` | Optional rationale recorded with the diagnosis. |

### `list_comparison_events`

List completed comparisons, newest first, when the user refers to earlier
comparison work without a `diff_hash` or when you need to find the hash for
another comparison tool. Each returned event identifies the engine pair and
comparison time, includes verdict and finding counts, and carries the
systemic-family rollup. It deliberately returns one row per comparison rather
than per finding, so use `list_system_diff_findings` for one event's findings
or `read_comparison` for the full classified element payload. The family samples
use the listing shape: coordinates, disposition, and only the source and target
values needed to render a list; full finding history remains available per event.
The per-event rows expose `column`, `detail`, `source_value`, and `target_value` beside
each evidence document; see the [Estate API reference](/docs/Genesis-API/API-Reference)
for the complete row contract.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `component_pair` | string | `null` | Optional engine pair filter, such as `postgres->databricks`; omit it to list every pair. |
| `limit` | integer | `25` | Maximum number of events, newest first. Omit it to use `25`; values are clamped to `1`–`20,000`. The result is sized by comparison families, not individual findings. |

The result is a bounded page. Check `truncated` before assuming the feed is
complete; `total_row_count` is exact when the page is complete and `null` when
more events remain.

Only comparisons the person you are working for can open are returned.
Visibility filtering can leave fewer rows than `limit`; hidden comparisons are
not counted. This adds one visibility-scope load to the event read.

An empty `comparison_events` list means no visible comparison has been run on
the deployment; characterize both sides and call `run_system_diff` first.

### `read_finding_ledger`

Read the findings that remain open across all comparison runs. Each result is
folded from the append-only lifecycle log and includes its durable `#N`, current
ledger state (`new`, `still_open`, or `reopened`), consecutive-run count,
originating run, and lineage. Results also include `last_seen_run_id` and
`rests_on_reopened_seal`; see the [ledger response fields](/docs/Genesis-API/API-Reference#get-api-estate-findings-ledger).
Resolved findings are omitted. Use
`list_system_diff_findings` for one comparison, `read_finding` for one
finding's complete case history, or `list_finding_dispositions` for recorded
diagnoses.

Only findings on comparisons the person you are working for can open are
returned; hidden findings are omitted and not counted. This tool has no
parameters. An empty `findings` list means nothing visible is open. The check
adds one visibility-scope load beside the ledger read.
For one comparison, `list_system_diff_findings` uses the same visibility boundary;
its `count` is computed after hidden findings are removed.

For an individual finding, read `evidence.detail` as its own detail. `family_pattern`
names the family template, with each number replaced by `#`; it is not the finding's
detail.

### `read_finding`

Read one finding in depth: its history, the reconciliation episodes it belongs to,
or the rows that evidence it. Use `read_comparison` first to get the finding's
numeric id or durable key. The response combines the requested records with the
current folded state and the tamper-evident history from the append-only event log.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `finding_key` | string | `""` | Durable finding key for episode or witness reads. |
| `finding_id` | integer | `0` | Numeric finding id for history reads; use the `#N` value from `read_finding_ledger`. |
| `include` | array of strings | `null` | Optional records to return: `history`, `episodes`, and/or `witnesses`. |
| `refresh` | boolean | `false` | Re-query both estates for witness rows when `true`. |

History requires `finding_id`; episodes and witnesses require `finding_key`.
If the identifier is unknown, the tool returns `success: false` with an actionable
error. When `include` requests history, its result includes `rests_on_reopened_seal` (a
reopen notice or `null`); see the [API ledger response fields](/docs/Genesis-API/API-Reference#get-api-estate-findings-ledger)
for how to interpret the notice and the additional reads it requires.
History is available only when the person you are working for can open the comparison
that minted the finding; otherwise it is answered as unknown. Episode sightings are
filtered individually by their comparison or estate visibility. A finding not minted
by a comparison is answered as unknown when none of its episode sightings are visible.
Witnesses are also limited to findings on comparisons the person can open. For the
obligation-ledger fields withheld when an episode sighting is hidden, see the [finding
episodes API contract](/docs/Genesis-API/API-Reference). One visibility scope is loaded
per call and shared by its requested history, episode, and witness reads.

### `request_evidence`

Ask for the facts behind one finding before anyone decides it. Read the finding with
`read_comparison` or `read_finding` first, then pass its finding key, comparison class,
and source- and target-side summaries; do not guess what caused the difference. This
files the same evidence request the Human Review finding pane's former **Request the
evidence** button filed. It does not change either estate or record a disposition on the
finding.

| Parameter | Type | Default | Required | Description |
| - | - | - | - | - |
| `finding_key` | string | `""` | Yes | Durable key of the finding, as returned by `read_comparison` or `read_finding`. |
| `comparison` | string | `""` | Yes | Finding's comparison class, spelled as the finding carries it. |
| `expected_summary` | string | `""` | Yes | Source-side facts from the finding, not a guess about the cause; at most 4000 characters. |
| `actual_summary` | string | `""` | Yes | Target-side facts from the same finding; at most 4000 characters. |
| `objects` | array of strings | `null` | No | Tables or columns named by the finding; omit when it names none. |
| `pair_fingerprint` | string | `""` | No | Finding's estate-pair fingerprint, when present. |
| `component_pair` | string | `""` | No | Finding's component pair, when present. |
| `family_signature` | string | `""` | No | Finding's family signature, when present; pass it when available so a repeated ask can match the request already filed. |

For example, replace each placeholder with the corresponding value from the finding:

```text theme={null}
request_evidence(
  finding_key="<finding_key from read_comparison>",
  comparison="<comparison class from the finding>",
  expected_summary="<source-side summary from the finding>",
  actual_summary="<target-side summary from the finding>"
)
```

With authentication disabled, the response returns `data.created` and `data.request`
with `request_id`, `kind`, `status`, and server-written `instructions`. The request is
attributed to `local operator (auth disabled)`. `created` is `false` when the same ask
for the finding—with the same comparison, objects, pair fingerprint, and family
signature—is already on file; the existing request is the answer, not a second request.

With authentication enabled, the tool does not file the request. It proposes it in Action
Review and returns `data.proposed: true`, `proposal_id`, the Action Review `status`, `url`,
`opened`, and `remediation_request_id`. A person may decide it there, or an agent may use
`decide_approval_request` on the person's behalf when asked or working on a goal they set.
Only a person who can read the finding may decide the request. A newly opened request is announced
with a card in the agent's thread. A repeated ask that is
already waiting returns `opened: false` and does not open another request; if the first
call could not send the card, a later ask can send it once. If the same ask is already
filed, the tool returns the existing `data.request` with `created: false` instead. Relay
`data.request.instructions` as written and tell the person the finding's decision now
waits on that evidence. Sending the request to whoever gathers it is a person's act, not
a tool call.

If the request was inserted but its read-back failed, the response has
`request_exists: true`, `unavailable: true`, `status: null`, and `card_sent: false`;
`proposal_id` is included when known. An `unavailable` or `fault` refusal that includes
`proposal_id` and `url` means the request exists but confirming it failed. For
`unavailable`, repeat the same ask to read the existing request; for `fault`, do not
retry, and give the person the `url`. Without `proposal_id`, no request was proposed.

The tool requires `ratify_source_contract`. A person who already declined the same ask
gets a `conflict` refusal; do not retry it. If the deployment's Action Review policy does
not admit the request, it returns `policy_denied` with the policy's reason. A caller
without `ratify_source_contract` is refused with `permission`. Invalid keys and prefixes
matching no finding are refused with `invalid`; a full key absent from the findings
ledger is refused with `not_found`. Genesis supplies `bot_id`, `thread_id`, and `user_id`
from the tool-call context; they are not caller parameters. Cost: one indexed
findings-ledger read to confirm the finding exists (without reading its evidence); a
short finding key needs one additional indexed lookup. A direct filing then costs one
remediation-ledger read and at most one insert. An authenticated proposal also costs one
remediation-ledger read and two Action Review ledger reads; opening a new request adds
one policy load, a second findings-ledger read, and one ledger transaction. A pending
request's card check adds two narrow ledger reads; the one call that sends its card also
adds one guarded update, one sealed event, and the card delivery.

### `request_test_case_approval`

Ask a person to approve the test cases currently in effect for one view, without changing
either database. Pass the `boundary_hash` the cases are stored under and a `target_node`
from those cases. Which call stores them depends on the run that will use them. For a
rewritten view's proof (`validate_migration`), check the cases with
`design_stimulus_campaign` and `check_claims_only=true`, which stores nothing, then store
them with `prepare_migration_prover` and pass the `boundary_hash` it returns. For a
trajectory or qualification campaign, `design_stimulus_campaign` stores them under the
`boundary_hash` you pass it; pass that same one here. A run groups cases into a
view by the last dot-separated part of `target_node`, so groups with the same final part
belong to the same view even if their preceding names differ.

| Parameter | Type | Default | Required | Description |
| - | - | - | - | - |
| `boundary_hash` | string | `""` | Yes | The boundary the test cases are stored under: for a rewritten view's proof, the `boundary_hash` returned by the `prepare_migration_prover` call that stored them; for a trajectory or qualification campaign, the one passed to the `design_stimulus_campaign` call that stored them. |
| `target_node` | string | `""` | Yes | A case's view name, such as `model.shop.stg_orders`. One view per call; view grouping uses its final dot-separated part. |

```python theme={null}
request_test_case_approval(
    boundary_hash="<boundary_hash the test cases are stored under>",
    target_node="model.shop.stg_orders",
)
```

Genesis supplies `bot_id`, `thread_id`, and `user_id` from tool context; they are not
caller parameters. With authentication enabled, the tool proposes the request in Action
Review. A signed-in person may approve or decline there; an agent may also use
`decide_approval_request` for the person when asked or when it is part of their goal. The
result includes `proposed`, `view`, case and request counts, `requests`, `not_asked`, and
`approval_status`. Each request includes its Action Review `url`, `status`, `opened`,
`case_set_id`, part number and total parts, and case count. Give the user each returned
URL. `opened: false` means the same cases are already waiting; that existing request is
the one to review. If the set needs multiple requests, each contains whole cases and
approving one approves only its cases; all requests must be approved for the view to be
fully approved. `not_asked` gives the parts that could not be proposed and why.

Approval is bound to the stored test cases: it remains in effect for later runs until a
case changes. A changed case set needs a new request. An unchanged set declined in Action
Review is not asked about twice; revise the cases to address the person's reason before
asking again. The reviewer-facing contents and what the approval means are described in
[Approve test cases for a view](/docs/Genesis-Prover/Roles-And-Approvals#approve-test-cases-for-a-view).
That page also explains the requester and decider attribution in the approval and decline
receipts, including when an approval is marked `self_approved`.
The Action Review brief also summarizes the situations Prover can list from stored view
SQL and which situations the test cases claim; the approval guide explains that summary.

With authentication disabled, there is no person to ask: the tool records the cases as
approved under `local operator (auth disabled)` and returns `approved: true`,
`approved_by`, `reviewed_by_a_person: false`, and `review_note`. It does not accept a
reviewer's name as attribution. This path runs only on a person-started turn; a product-
started turn such as a wake or mailbox notice is refused without approving anything.

Asking needs `view_connections` and a signed-in person. With authentication enabled,
if no signed-in person started the turn, it refuses with `unidentified` and tells the
caller that a person must ask; otherwise a missing `view_connections` permission is
reported as `permission`. Any signed-in person who can see the request's full review
scope can open and decide it in Action Review, without `ratify_source_contract`. For a
boundary with snapshots, that scope is every snapshot behind the view's test cases. For
a boundary prepared with `prepare_migration_prover` and no snapshots, it is every
connection sealed into the request: the source, target, and any warehouse connections.
An older request that sealed no connections uses every connection in the pair recorded
for its boundary. For the legacy-request visibility rule, see [Approve test cases for a
view](/docs/Genesis-Prover/Roles-And-Approvals#approve-test-cases-for-a-view). When every
case for the view is already
approved and unchanged, it asks nothing and succeeds with
`approval_status: "fully approved"`, `approved_by` and
`approved_at`. It refuses with `not_found` when no cases
are stored for the view and boundary; with `conflict` when they are
declined without changes, inconsistent about the output or condition, repeated across
groups, or cannot be shown whole and exactly; and with `invalid` for an empty final
`target_node` part. A request withdrawn because cases changed must be made again for the
current cases. A policy that does not admit the request returns `policy_denied`.

When called from outside Genesis over MCP or `/api/tool_call`, the response points
`next` to `action_review_request_status` for the first pending request. Use that
tool with each returned `proposal_id`, and share the returned
`data.requests[].url` with the user in the meantime. Do not call
`request_test_case_approval` again to check the result. See
[`action_review_request_status`](#action_review_request_status) for its response fields
and states.

Cost: the tool reads the view's stored test-case versions and up to 200 recent declined
or withdrawn requests to find earlier decisions. For each request still needing approval
it reads the Action Review ledger twice; opening a request also reads the view's stored
text from the newest scan of the request boundary, or else searches the 50 newest scans,
and parses its SQL and conditions to list situations. It reads the boundary's target
profiles to find a mapped rewrite; when that rewrite can be read, its text and conditions
are parsed too. A new request also loads policy and writes a ledger transaction. Sending
a card adds two ledger reads and a write. With authentication disabled, it reads the cases
and performs a status read and update in one transaction.

### `adjudicate_findings`

Send the findings from a completed system comparison—whether it came from a graded
proof, a comparison-only proof, or a compare run—to the independent
Adjudicator for read-only reproduction and routing. The Adjudicator records a
typed verdict for each finding as `stands`, `spec_defect`, `target_defect`,
`platform`, `question`, `spec_ambiguity`, `candidate_improvement`, or
`no_deviation` or `instrument_defect`, with rationale and query receipts. See the
[False alarm (Prover) guidance](/docs/Genesis-Prover/Roles-And-Approvals#false-alarm-prover)
for the latter outcome. `no_deviation` records that
the Adjudicator examined the finding and found nothing to route; it requires a
one-line `reason`, is neither `stands` nor an abstention, and routes to nobody.
`candidate_improvement` records a deliberate build deviation that may be better
than the declared behavior; it is queued for human review and is not a license.
The tool returns a running `adjudication_id`; with `notify` (the default) this
thread is told when the Adjudicator has submitted its verdicts, with the record
`get_adjudication_run` returns, so there is nothing to poll. An unknown
comparison or a comparison with no findings is refused before a proceeding is
started. The spawned proceeding is visible on the **Prover Adjudicator** agent
page and is titled `Adjudication <first 12 characters of diff_hash>`, so a
reviewer can open the thread and read the Adjudicator's reasoning.

The Adjudicator checks the model provider before opening the proceeding. If it cannot
answer, the tool returns an `unavailable` refusal with `cause` and creates no
proceeding; follow that remedy before retrying. The check uses the shared
[`llm.provider_preflight_ttl_seconds`](/docs/Setup/Advanced-Settings#llm-streaming-timeouts)
window.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Content hash of the completed comparison to adjudicate, from `run_system_diff` or `list_system_diff_findings`. |
| `mode` | string | configured `estate_char.adjudicator.mode` (`silent`) | Optional per-call override: `silent` persists verdicts to the adjudication log only; `active` also stages routable verdicts as a disposition package for human approval. Allowed values are `silent` and `active`. |
| `notify` | boolean | `true` | Tell this thread when the proceeding completes or fails, with the record `get_adjudication_run` returns: on your next tool result if you are mid-turn, or as a new turn once you are idle. Set `false` only to poll `get_adjudication_run` yourself. |

The configured mode is fail-closed: an unset, uninitialized, or unrecognized
value is treated as `silent`. The kickoff message is a table of contents, not a
copy of the materials: it names the proceeding's sections, their counts and
serialized sizes, and the constitution pin. Read every section through the
Adjudicator-only `fetch_adjudication_materials` tool, starting with `doctrine`
and continuing each page until `next_offset` is `null`. Each citable register
entry has an `entry_id`; IDs use the forms
`disposition:<finding_key>`, `ruling:<ruling_id>`, `rule:<rule_id>`,
`fork:<axis_id>`, or `reference:<basis_id>`. A `reference:` entry is available
for a migration comparison without a sealed spec and means the target carries
the source's content; it does not license content drift. The briefing must fit
the thread message-size limit; an oversized briefing is refused before the
proceeding or Adjudicator instance is created.

Reusing the same `(run_id, round_n)` returns the existing proceeding; it does not
re-mode it. The response's `requested_mode` records the mode this call named, and
`mode_basis` is non-null only when that requested mode was dropped because the
existing proceeding uses another mode. A proceeding's mode is fixed when it opens,
so choose `silent` or `active` on the call that creates the round.

With `notify` (boolean, default `true`), the thread that opened the proceeding is
told when it completes or fails, on its next tool result or in a new turn after it goes
idle. The wake carries the same record `get_adjudication_run` returns — verdicts
projected, `progress` beside them — so there is no need to poll; the response's
`next_step` says so while the wake is armed. When that record is too large for the
mailbox, the new-turn form carries it without its verdicts and says so under
`verdicts_omitted_from_wake`, naming the `get_adjudication_run` call that reads them.
Set `notify=false` to poll `get_adjudication_run` yourself. A caller without a Genesis
thread is not armed.

### `adjudicate_conformance_run`

Send a parsed conformance suite result to the independent Adjudicator after the
suite grades a build against a sealed specification and before the builder sees
the raw output. The Adjudicator reproduces every non-`PASS` check read-only
against the target and routes it as `stands`, `spec_defect`, `target_defect`,
`platform`, `question`, or `spec_ambiguity`. The run is identified by the
canonical digest of the supplied result document, and the proceeding verifies
that `spec_hash` matches the run's recorded `spec_sha256` before it opens.

This intake runs only in `silent` mode: verdicts are persisted to the
adjudication log and do not stage a disposition package. Partial clause
coverage is accepted, and findings whose cited clause was not supplied are
listed as `sealed_spec.findings_without_clause`; supplying clauses for none of
the non-`PASS` findings is refused. A run without durable findings returns
without opening a proceeding; the API response includes the reason beside
`no_findings`. With `notify` (the default) this thread is told when the proceeding
completes or fails, with the record `get_adjudication_run` returns, so there is
nothing to poll; with `notify=false`, poll `get_adjudication_run` with the
`adjudication_id`. `adjudication_id` is not a generic run id. Use
`get_conformance_fix_brief` after completion.

The run document preserves each finding's `durable_id` (the persisted `#N`,
when one exists) beside its finding key, and includes `as_of`, the time the
grading run observed the estate. When a clause declares `candidate_readings`,
the materials also include its passing rival checks when another reading on the
same fork failed; those checks are marked `role: "fork_context"` and provide
measurement context rather than additional findings to route. The kickoff is a
table of contents; read the pinned doctrine, identity, cited clauses, findings,
and any other listed sections through `fetch_adjudication_materials`, continuing
pages until `next_offset` is `null`.

The materials identify the build under test in `conformance_run.target` using
the resolved target endpoint's `catalog` and optional `dialect`. When no target
endpoint resolved a database, `conformance_run.target` is `null` and the
materials do not name the estate. Completed grading runs can also resolve their
source and target read-only endpoints from `summary.provenance` when the pair
was recorded there, as well as from the top-level snapshot fields. Findings
carry the measurements available from the grading run: `mismatched_key_count`,
a bounded `mismatched_keys_sample` (up to 20 keys),
`mismatched_keys_truncated`, and the sealed `source_sql` and `target_sql`. For
a finding covering multiple obligations, measurements stay with each
`obligations` entry; each entry also preserves its declared fork axis and reading
when available, so a fork leg remains identifiable in the downstream finding and
fix brief. A top-level `measurements` block is included only when the finding has
one obligation.

The run document also includes the open findings from the `type_family` durable
ledger, not only obligation findings. Those results carry `tier: "type_family"`,
the durable `durable_id` when present, and the finding's `locus`; when the family
grader recorded both halves of the comparison they also carry `expected` and
`observed`. Their cited clauses use the same `type_family` tier, so the
Adjudicator can distinguish a declared-type finding from an obligation that uses
the same sealed item identifier.

Each failing check is matched to a durable finding by its exact locus first. If
the run has no matching locus, the item's declared `spec_item_id` can supply the
match only when exactly one open durable finding belongs to that item. This lets
runs without a recorded locus proceed while keeping one proceeding rule per
durable finding. An item with multiple open findings, or a check that resolves to
none of the item's open findings, is refused rather than emitted with a composite
`<spec_item_id>:<obligation>` key that the caller cannot reconcile. Findings that
are already closed are not part of this open-finding match.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `conformance_run` | object | none | Parsed suite result containing `run_id`, `target`, `target_identity`, `spec_sha256`, `results`, and `summary`. Each result should include `id`, `clause_id`, and `status`; non-`PASS` results become findings. Results may also carry `durable_id`, `locus`, `expected`, and `observed`; the run document may carry `as_of`. |
| `spec_clauses` | array of objects | none | Parsed sealed-spec clause records, such as `id`, `claim`, `citation`, `tier`, `scope`, `falsified_by`, and `candidate_readings`. For a cited clause whose `ruling.position` is a non-empty string, the materials also carry the ruling in force with any present `date`, `class`, `position`, and `license` fields; `superseded_rulings` is not carried. Coverage may be partial, but must cover at least one failing finding. |
| `spec_hash` | string | none | SHA-256 hash of the sealed clause file. It must match `conformance_run.spec_sha256`. |
| `connection_ref` | string | `""` | Read-only database connection name used to query the built target and its donor. |
| `target_reference` | object | `null` | Optional target and donor addressing: `dialect`, `catalog`, `schema`, `classic_catalog`, `classic_schema`, `warehouse_id`, `label`, and `bindings`. |
| `estate_id` | string | `""` | Optional estate name whose settled rulings are included in the license/settlement register. |
| `doctrine_addendum` | string | `""` | Optional doctrine block appended to the pinned Adjudicator constitution for conditions the product doctrine does not state, such as a benchmark blindness charter. The server content-addresses the rendered bytes and records the digest on the proceeding. Maximum length `20000`. |
| `doctrine_sha256` | string | `""` | Optional SHA-256 digest for `doctrine_addendum`. When supplied, it must match the bytes rendered by the server; a mismatch refuses intake. |
| `notify` | boolean | `true` | Tell this thread when the proceeding completes or fails, with the record `get_adjudication_run` returns: on your next tool result if you are mid-turn, or as a new turn once you are idle. Set `false` only to poll `get_adjudication_run` yourself. |

Example:

```python theme={null}
adjudicate_conformance_run(
    conformance_run=run_document,
    spec_clauses=sealed_spec_clauses,
    spec_hash=run_document["spec_sha256"],
    connection_ref="migration_readonly",
    target_reference={"catalog": "target", "schema": "analytics"},
)
```

### `get_adjudication_run`

Read a proceeding's status, mode, constitution pin, materials manifest, and
submitted verdicts for either a completed comparison or a conformance run. If
its handoff instance ended without submitting, the run is reconciled to
`failed`, and a replacement can be started with the tool that opened that
proceeding.

A `running` status means only that the Adjudicator has not submitted; it does
not say whether the seat is still working. `run.progress` is the best EVIDENCE
about that, and it is evidence rather than proof — read it as such.

`phase: "working"` says only that the thread has been written to at some point;
the message count is cumulative, so it is not a liveness verdict.
`last_activity` is the seat's own freshest write and it does not advance while
the seat is inside one model completion — five to ten minutes is normal at this
seat's timescale — so a still `last_activity` is not on its own a stall.
`streaming` is three-valued: `true` with a recent `last_chunk_at` means the
completion is still delivering and the seat IS working however still
`last_activity` looks; `false` means the window passed with no chunk; `null`
means this response could not DECIDE stream liveness, which is not the same as
the stream having stopped. `null` has three causes: no chunk reading exists in
the process that served you, no staleness window was available to compare
against, or `last_chunk_at` did not parse. The last two still publish
`last_chunk_at` and `stream_chunk_count`, so `streaming: null` beside a non-null
`last_chunk_at` means a reading was held and could not be judged — not that
nothing measured it. A null `last_activity` is a third case again — read
`unavailable_reason`, which says which silence it is.

So: stale counters WITH `streaming: true` is a working seat. Stale counters with
`streaming: false` is the stall. Stale counters with `streaming: null` is
liveness UNKNOWN, and the honest report is that this response did not settle it —
not that the seat is dead, and not that it is fine. Quote what you read and say
which of those three it is, rather than converting any of them into a verdict.

A terminal proceeding reports its own end word as the phase with the counters
null — nothing read them, and null is not zero — and `finished_at` says when it
ended. A status this reader does not recognise reports `phase: "unknown"` with
the status named in `phase_basis`: it is neither classified as running nor
treated as finished.

Each returned verdict also carries its measured subject as `object` and `column`.
The briefed finding supplies those coordinates when materials are present; on a
terminal re-read without materials, Genesis resolves them from the durable finding
identified by `finding_key`. If neither source names a coordinate, the fields remain
present with `null` values rather than being omitted.

Narrow before paging: `verdict_ids` and `outcome` filter the proceeding's verdicts,
then `verdict_offset` and `verdict_limit` page that narrowed set. An empty
`verdict_ids` list or an outcome outside the recorded vocabulary is refused.
`verdict_page.total` is the narrowed set's size, `returned` is this page's size,
and `next_offset` is the next offset or `null` when the set is complete. Advance
using `next_offset`, not the requested limit. `verdict_selection` echoes the
filters and page coordinates so the response identifies which rows it contains.
For example, `get_adjudication_run(adjudication_id="...", outcome="question",
verdict_limit=25)` reads the first page of question verdicts.

Reading `progress` for a running proceeding costs a thread read per call (and,
where a handoff is recorded, the orphan probe beside it), so poll deliberately
rather than in a tight loop.
Narrowed or paged reads also count the matching verdict set; if an orphaned
proceeding is reconciled during one of those reads, the selected verdicts are
read again afterward.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `adjudication_id` | string | none | Proceeding ID returned by `adjudicate_findings` or `adjudicate_conformance_run`. |
| `verdict_ids` | string\[] or null | `null` | Read only verdicts with these `verdict_id` values. This narrows the proceeding before paging; an empty list is refused. |
| `outcome` | string | `""` | Read only verdicts with this recorded outcome. An unknown outcome is refused rather than returning an empty set. |
| `verdict_offset` | integer | `0` | Starting offset within the narrowed set. Must be nonnegative; advance using the previous response's `verdict_page.next_offset`. |
| `verdict_limit` | integer | `0` | Maximum verdicts in this page. `0` is the tool runtime's omitted value and reads the whole narrowed set; otherwise use at least `1`. |

### `fetch_adjudication_materials`

Read one section of the Adjudicator's kickoff table of contents. This is a
private tool for the pinned `Adjudicator` identity and only serves the
proceeding in the caller's current thread; it does not perform a live estate
read. The kickoff carries no materials, so use this tool for everything the
Adjudicator must read: start with `doctrine`, then read each listed section to
completion before submitting a verdict.

The available sections are `doctrine` (the pinned constitution and proceeding
addenda), `identity` (what is being compared and the read-only connections),
`advisories` (tier-0 flags), `license_register`, `cited_clauses` (for a
conformance run), `prior_verdicts` (earlier rulings on the same pair-scoped
findings), and `findings`. A section is listed only when that proceeding holds
it. `prior_verdicts` contains the newest earlier verdict for each finding, with
`finding_key`, `verdict_id`, `adjudication_id`, `outcome`, `confidence`,
`rationale`, and `recorded_at`. Comparison and grading-run proceedings include
this section, even when its list is empty. A grading-run proceeding includes
prior verdicts only for pair-scoped durable findings. The direct
`adjudicate_conformance_run` tool includes an empty `prior_verdicts` list because
the supplied suite's test IDs do not identify an estate pair. Read the section
before deciding whether your verdict differs. When a prior verdict is found under
the same finding's key from another compared scope, its entry also includes
`aliased_from`, the key on which that verdict was recorded. Finding identity is
scoped to registered estate-pair ownership, not just the databases being compared;
the [Prover's scope and finding guidance](/docs/Genesis-Prover/Agents-And-The-API#comparison-cards-in-chat)
defines which pair keys belong to the same finding identity class.
Register pages list entry metadata without the rationale and qualification; request
those fields by naming the corresponding `entry_ids`.

Pages default to `20` entries and accept at most `50`, but the transport byte
cap can return fewer than requested. Use the response's `next_offset` as the
next `offset` until it is `null`. The response reports unknown named IDs rather
than silently dropping them. The read loads the proceeding's stored materials
snapshot, then slices it; it does not query either comparison endpoint. A
`doctrine` read also reloads and verifies the pinned constitution before serving
it.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `adjudication_id` | string | none | Proceeding ID from the mission briefing. |
| `section` | string | `findings` | Section to read: `doctrine`, `identity`, `advisories`, `license_register`, `cited_clauses`, `prior_verdicts`, or `findings`. |
| `offset` | integer | `0` | Zero-based starting offset. Must be a whole number from `0`. |
| `limit` | integer | `20` | Number of entries to return. Must be a whole number from `1`; values above `50` are capped at `50`, and the transport byte cap may return fewer. |
| `finding_keys` | array of strings | none | Named finding keys to fetch instead of paging the findings inventory. Unknown keys are reported in the response. Use with `section: "findings"`. |
| `entry_ids` | array of strings | none | Named register `entry_id` values to fetch their full rationale and qualification instead of paging the register inventory. Unknown IDs are reported in the response. Use with `section: "license_register"`. |

Example:

```python theme={null}
fetch_adjudication_materials(
    adjudication_id=adjudication_id,
    section="doctrine",
)

fetch_adjudication_materials(
    adjudication_id=adjudication_id,
    section="findings",
    offset=0,
    limit=20,
    finding_keys=["orders.total_mismatch"],
)
```

### `get_conformance_fix_brief`

Read the builder-facing brief after a conformance adjudication completes. The
brief contains the run ID, target, specification hash, and one item for each
`target_defect` verdict. This conformance intake runs only in `silent` mode, so
`candidate_improvement` verdicts do not produce a builder order here. Each item
includes the finding key, clause ID, and the charged rule with its citation, but
omits grading numbers, the Adjudicator's rationale and confidence, and query
receipts. An empty `items` list means the run's failures were assigned to the
specification, platform, or an escalation; the builder has no rule-based fix
request.

This tool refuses an unknown or incomplete proceeding, a comparison proceeding,
or a proceeding whose stored materials cannot be read.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `adjudication_id` | string | none | Completed conformance proceeding ID returned by `adjudicate_conformance_run`. |

### `submit_adjudication_verdicts`

This is the Adjudicator's private submission tool, not a general estate-agent
tool. Submit one typed document containing the verdicts reached so far. Each
verdict requires `finding_key`, `outcome`, `confidence` (`high`, `medium`, or
`low`), `rationale`, and at least one receipt with `query` and `observed`. A
`no_deviation` verdict additionally requires a non-empty one-line `reason`
saying what was examined and why there was nothing to route; it cites nothing.
A `stands` verdict must also include a non-empty
`license_refs` array containing the `entry_id` of a covering entry in the
proceeding's `license_register`; citations that do not resolve to that register
are refused. A `disposition:<finding_key>` entry covers only its own finding,
while `ruling:`, `rule:`, `fork:`, and `reference:` entries identify broader
classes whose
coverage must be supported by the verdict's receipts. A `fork:` entry identifies
an axis declared by the sealed spec, and the receipts must establish that its
measurements settled the fork. A `reference:` entry is valid only for a
migration without a sealed spec; its receipts must show the same content on the
source and target endpoints, and a content difference remains drift rather than
a covered representation difference. If no register entry covers a deviation,
route it on its merits instead, such as `question` with a `provisional_position` when
the data owner must settle it. Use `provisional_position` for `question` and
`spec_ambiguity` escalations; those outcomes do not stage dispositions. A
`candidate_improvement` verdict must include an `improvement` object with
non-empty `build_behaviour`, `declared_behaviour`, `clause_ref`, `value`, and
`risk` strings. Its optional `mode` is `pocket` by default or `blocking`; it
cannot include `license_refs`. The object may also include `waiver_expires_at`
(optional string, default `null`; a future ISO-8601 date-time) and `waiver_owner`
(optional string, default `null`, naming who answers for the waiver if accepted). If the proposed expiry is unreadable
or has passed, only those terms are dropped; the improvement is still filed, and the
response's `waiver_terms_dropped` explains why. See [Prover docket review](/docs/Genesis-Prover/Roles-And-Approvals#decide-a-court-docket-or-an-improvement-docket-item)
for how a person reviews the proposed terms. For comparison proceedings, earlier verdicts on the
same findings are included in `prior_verdicts`. If your outcome differs from that
ruling, include `departs_from` with exactly its `verdict_id` and a non-empty `why`
explaining what you measured that it did not. Submission is refused if a changed
outcome omits this field, names another verdict, or supplies it when there is no
prior ruling or your outcome agrees. Your confidence must reflect your own receipts,
not the earlier seat's confidence.

For example, include the optional waiver terms inside the improvement object:

```json theme={null}
{
  "waiver_expires_at": "<future ISO-8601 date-time>",
  "waiver_owner": "Finance operations"
}
```

Replace the expiry placeholder with an actual future date-time.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `adjudication_id` | string | none | Proceeding ID from the Adjudicator's mission briefing. |
| `verdicts_document` | object | none | Object with a `verdicts` array containing the typed verdict entries. Every `stands` entry must include `license_refs` that resolve to register `entry_id` values from the mission materials. A `no_deviation` entry must include its one-line `reason`. A verdict differing from its finding's prior outcome must include `departs_from: {"verdict_id": "<prior verdict id>", "why": "<what you measured that it did not>"}`. A `candidate_improvement` entry must include its `improvement` object; omit `mode` for the default `pocket` behavior. The object may include optional string fields `waiver_expires_at` and `waiver_owner` to propose waiver terms for approval. |

Only the pinned `Adjudicator` identity may submit. A finding without a verdict
does not count as `no_deviation`: submit an explicit `no_deviation` row when it
was examined and nothing needed routing. If a document covers only some
findings, the accepted verdicts are persisted and the refusal returns
`proceeding: "awaiting_coverage"` plus `unruled_finding_ids`; send an additional
document for those IDs rather than resending accepted verdicts. The proceeding
completes only after every finding carries a verdict. In `silent` mode, accepted
verdicts are persisted to the adjudication log and nothing else changes. In
`active` mode, each `target_defect` verdict and `pocket` `candidate_improvement`
verdict is sent back immediately under the Adjudicator's name; the finding stays
open until a fresh comparison shows the fix, and nobody approves the send-back.
`blocking` candidate improvements write a docket entry but send no builder item
back. `spec_defect`, `platform`, and `instrument_defect` settle a difference
without a fix, so they are staged together as one disposition package for human
approval. No package is staged when there is nothing requiring approval. The
candidate-improvement docket entry is written for human review and is never a
license. `no_deviation`, `stands`, `question`, and `spec_ambiguity` do not stage.
The response also reports
`docket_entry_ids`, `held_for_review`, `staging_skipped`, `docket_discarded`, and
`waiver_terms_dropped`. Each dropped-terms item explains why an improvement's proposed
waiver terms were omitted; the improvement remains filed. Filing an improvement also attempts to open its Action Review
request automatically. `docket_requests` returns one result per finding, with
`finding_key`, `proposal_id`, `status`, `url`, and `opened` (`true` only when this
submission created the request), for entries that remain open. An entry already
accepted or rejected is named in `docket_discarded` instead and has no
`docket_requests` row. An `error` means this filing opened no new request, not
always that no request exists: with a `proposal_id`, the row identifies the
finding's current request; with no ID, `refused` means no request is asking for
the finding, while `unavailable` or `fault` means its request state is unknown.
The docket entry remains filed in each case; do not file it again to ask for
approval. Candidate-improvement docket entries can be filed on Snowflake ledgers
as well as the other supported substrates. On completion,
`verdict_count` and these proceeding-wide fields describe the union of verdicts
accepted across all documents, not only
the latest submission. In `active` mode, `sendbacks_applied` lists finding keys
sent back by this proceeding, including keys already applied on an earlier retry;
`sendbacks_made_stale` maps each send-back to open-package items it made stale.
A send-back naming a finding the ledger does not hold closes the proceeding as
`blocked`; a finding diagnosed by a person after the proceeding opened keeps that
diagnosis and is returned in `staging_skipped`. Failed writes or findings that
moved during a send-back leave the proceeding open for retry with the same
document. Other routable verdicts stage on the
comparison named by the proceeding manifest's `diff_hash`; this is the
comparison ledger the proceeding holds, not the subject document's hash. If
that comparison is absent from the instance, the verdicts remain recorded but
the proceeding closes as `failed` with `proceeding: "blocked"`, because retrying
cannot make the named ledger appear. If the ledger refuses the disposition
package, the proceeding also closes as failed with `proceeding: "blocked"`; the
same document will meet the same refusal, so report it and open a new proceeding
rather than retrying. A failed package write or linkage refusal leaves the
proceeding open for retry with the same document. Every refusal includes
`proceeding` and `next_step`: `awaiting_coverage` means send
an additional document for exactly the returned `unruled_finding_ids`; `open`
means correct and retry as directed, `closed` means the terminal record stands,
`blocked` also covers a stored finding inventory that cannot be read: that proceeding
closes as `failed`, returns `inventory_error`, and records
`error_type: "inventory_unreadable"`. Report it and open a replacement proceeding rather
than retrying. In all cases, `blocked` means the stored materials cannot support any
submission, and
`unknown` means the call did not establish the state, so read the run with
`get_adjudication_run` before deciding what to do next.

For how human reviewers accept or reject these entries, including the Action
Review path for agent-filed candidates, see the [Estate improvement docket
API](/docs/Genesis-API/API-Reference#estate-improvement-docket). The reviewer-facing
statement of what an accepted finding's licence covers is described in
[Prover roles and approvals](/docs/Genesis-Prover/Roles-And-Approvals#decide-a-court-docket-or-an-improvement-docket-item).

### `propose_finding_disposition_package`

Stage an agent's diagnoses for multiple findings from one system comparison for
human review. Staging writes no dispositions. By default, the returned
`approval_url` opens the package's own Prover approval page, where a reviewer sees
each proposal beside the finding's current source and target evidence. Reviewers can
approve or decline the package exactly as staged, but cannot edit, drop, or re-diagnose
an item. If an item is wrong, decline the package and ask for a corrected one.
Unless `for_bundle` is `true`, the tool also creates one Action Review item with
action type `prover.approve_disposition_package.v1` for this package generation.
For a package with its own request, give the person the returned `approval_url`
and `action_review_proposal_id`. The same package generation reuses its Action
Review item on replay, and a declined or policy-denied item is not replaced by
another approval request.
When `for_bundle` is `true`, the package is staged without its own Action Review
item or approval request so a later `propose_approval_bundle` can make the bundle
the person's single request. In that case, use the bundle's link instead of this
package's `approval_url`.
Any signed-in person can approve the package, including the person who asked the agent
to stage it; no special approval permission is required. When asked or acting on a goal
the person set, the agent can also use `decide_approval_request` to approve or reject the
package request for them. See [Prover roles and approvals](/docs/Genesis-Prover/Roles-And-Approvals#approve-a-disposition-package)
for the approval record and workflow.
A correspondence rule already claimed by a live bundle request prevents a new
package request: if detected during staging, the package is not staged; if the
claim wins during request minting, the package remains staged and
`action_review` reports `claim_refused` without a request. See the [disposition
package API reference](/docs/Genesis-API/API-Reference#estate-endpoints) for the
refusal codes. A replay checks the existing request against a fresh rule claim.
If the request pins a rule its claim did not hold, it is ended and reported as
`drift`; if another live request now holds a claimed rule, it is ended and
reported as `claim_refused`. If rule holds cannot be read and no unclaimed
pinned rule was found, the request remains standing and the response reports
`unavailable`. After `drift` or
`claim_refused`, ask again to mint a request for the package as it now stands.
If an agent's composite bundle adopts the package request, that bundle request
holds the package: an approval mint for the same package will not create a
competing Action Review item. Decide the bundle request first; after it is
declined or policy-denied, stage a new package to ask for approval again.
The package's native approval and unsign surfaces refuse while that Action Review item owns the
decision; a person decides it from the package approval page, which uses Action Review
behind the scenes, or an agent uses `decide_approval_request` on the person's behalf.
For the approval flow, including an inconclusive
result when post-approval read-back fails and the one-time card behavior on replay,
see [Prover roles and approvals](/docs/Genesis-Prover/Roles-And-Approvals). For how an
Action Review approval affects a promoted rule's review record, see
[Action Review also reviews promoted rules](/docs/Genesis-Prover/Roles-And-Approvals#action-review-also-reviews-promoted-rules).
For Snowflake storage options for the estatechar review-event and findings records,
see [Estatechar store settings](/docs/Setup/Advanced-Settings#estatechar-store-settings).
Packages refuse `target_defect`, whether it is listed directly, selected by family,
or included in a corrective package: a send-back is applied directly with
`disposition_system_diff_finding(disposition="target_defect")`, never staged for
approval. Active Adjudicator `target_defect` verdicts are also applied directly.
If a difference requires a fix, do not propose a package for it.
Write `plain_summary`
for the person signing in ordinary business English, and `note` for an engineer
reading the technical record. The `justification`, each `plain_summary`, and each `note`
are shown to the reviewer. Do not ask the reviewer to change, edit, correct, or amend an
item; if an item might be wrong, explain what would make it wrong and ask the reviewer
to decline the package so you can stage a corrected one.

Package staging, including packages with staged rules, works on a Snowflake ledger.
Before writing the package event or any staged rule, staging checks whether a minted
rule can pass durable qualification; a refused rule therefore leaves neither the
package nor that rule written. The package retry identity is claimed with an
insert-if-absent `MERGE`, so a repeated request returns the winning proposal instead
of creating another one. Open package claims use a guarded update; if another event
holds the claim, the request is refused. That guard is not a serialization guarantee
for two truly concurrent claimers; the approval service's door check is the
concurrency boundary. Approval that promotes a rule also works on Snowflake. It
checks each promotion before writing its rule; a refused promotion writes nothing,
and an Action Review approval still applies every item or none. If the store changes
between a check and its write, or a statement fails, the Snowflake transaction rolls
back as a whole. If ledger read-back cannot account for a package result — for
example, no row or more than one row exists at the claimed address — staging fails
closed and returns the audit reference for the recorded derivation failure; it does
not silently treat an ambiguous package as successful.
For the Snowflake batch-write performance of approvals that create standing rules,
see [Prover roles and approvals](/docs/Genesis-Prover/Roles-And-Approvals#approve-a-disposition-package).

Each approved diagnosis stays attributed to the agent as its proposer, with the human
reviewer recorded as the person who approved it. When the reviewer approves a
package, each licensed
disposition other than `target_defect` also resolves matching
`unexpected_change` blockers in the selected Human Review population when the
package covers them completely. Retracting that approval re-opens the
package-bound blockers it resolved; see the [disposition package endpoints](/docs/Genesis-API/API-Reference#estate-endpoints)
for response counts and API details. The review-population API reports these
package-resolved members as `resolution="exception"`; a person's separate
recorded ruling is reported as `resolution="ruling"`.

A proposed disposition is a recommendation, not a decision. The reviewer approves
or declines the package exactly as staged, as a whole; no row can be changed on the
package. Propose your best reading rather than withholding one: declining to choose
leaves the reviewer to sort through the findings one at a time. When the choice
depends on something only the reviewer can answer — such as whether the difference is
expected for this pair of systems from now on or accepted only for this run — say
exactly that in `plain_summary` and propose anyway. The review surface shows
`plain_summary` on the row and uses it to group the package, while `note` appears
behind a collapsed technical-note disclosure.

Do not propose `target_defect` or `spec_defect` for a finding whose latest
Adjudicator verdict is `question` or `spec_ambiguity` unless the owner has
answered it. Ask the owner in chat, then record their answer with
`record_clarification` on an estate of the comparison's pair, after the seat
asked. Have the owner ratify it on the review page while signed in; then cite its
`clarification_id` on that finding's item. The citation carries the defect only
when a signed-in person ratified the clarification after the seat asked. An
agent-certified clarification, or one ratified with authentication disabled,
does not carry it; on a stack with authentication disabled, the owner records
the diagnosis themselves on the review page. A `promote_delta` or `waived` item
can instead cite the owner's ruling behind it: the clarification must be
recorded on an estate of this comparison's pair and not overturned;
ratification is not required, and the item shows its provenance label. A
citation on any other item is refused. The other route is to seal the owner's
answer into the spec and re-open adjudication so the seat can rule on it.
Dispositions that charge no defect can still be proposed.

For agent-versus-caller attribution when Genesis invokes this tool, see the
[disposition package API reference](/docs/Genesis-API/API-Reference#post-api-estate-comparison-events-diff_hash-disposition-packages).

An item proposed as `waived` grants a time-limited exception and must carry a
future `waiver_expires_at` and a `waiver_owner`. Set the terms on each item, or
use the package-level defaults; an item's own values take precedence, and an
omitted owner defaults to `on_behalf_of`. Waiver terms are part of the retry
identity, so changing only a term does not replay the earlier proposal.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Content hash of the comparison whose findings are being diagnosed, from `run_system_diff`. |
| `title` | string | none | Short package summary shown on the approval page; maximum `200` characters. |
| `justification` | string | `null` | The case for approving the package, in plain business English: why you are asking and what the approver is taking on. Shown above the items; maximum `4000` characters. |
| `proposer_display_name` | string | `null` | A readable, self-declared label for the proposing agent. It is shown as an unverified claim and never replaces the authenticated proposer identity; maximum `200` characters. |
| `items` | array of objects | none | One object per finding with required `finding_key` and `disposition`, plus optional `plain_summary`, `note`, `rule_id`, `clarification_id`, `waiver_owner`, and `waiver_expires_at`; a finding may appear only once. Each item's `clarification_id` is a string, defaults to `null`, and is limited to `64` characters. Waiver terms are accepted only for `waived` items. Use exactly one of `items` or `select`. |
| `select` | object | `null` | Family selector with `family_signature`, one `disposition`, and optional `note`, `plain_summary`, and `rule_id`. The server expands it to this comparison's undiagnosed findings in that family, whatever their status; it is valid only for an initial package. If `disposition` is `waived`, package-level waiver terms apply to every expanded item. |
| `waiver_owner` | string | `null` | Default owner for `waived` items that do not set an item-level owner; falls back to `on_behalf_of` when omitted. |
| `waiver_expires_at` | string | `null` | Default ISO-8601 expiry for `waived` items that do not set an item-level expiry. It must be in the future when staging. |
| `for_bundle` | boolean | `false` | Stage the package without an individual approval request because it will be carried by one `propose_approval_bundle` request with the comparison's other open items. Use the bundle's approval link for the person. |
| `source_message_id` | string | implicit | Source user-message id from the active Prover chat; used with the thread id to make retries of the same request idempotent. |
| `input_metadata` | object | implicit | Active message metadata. When it contains authoritative `prover_context`, the package is bound to the captured comparison, scope, and member identities. |

`disposition` must be one of `target_defect`, `source_drift`, `promote_pi`,
`promote_delta`, `spec_defect`, `instrument_defect`, or `waived`. `note` is optional rationale
shown beside the evidence and is limited to `2000` characters. `plain_summary`
is optional, limited to `600` characters, and should be one sentence explaining
what approving the diagnosis actually means without schema or migration jargon.
Each item accepts only `finding_key`, `disposition`, `plain_summary`, `note`,
`rule_id`, and `clarification_id`; the optional `clarification_id` is the
recorded owner answer or ruling described above. See the [API
reference](/docs/Genesis-API/API-Reference#post-api-estate-comparison-events-diff_hash-disposition-packages)
for how unknown request fields are reported.
The package must contain at least one item and at most `2000` items; each finding
must be an open finding on the comparison and must not already carry a diagnosis.

The response includes `package_id`, `diff_hash`, `mode: "initial"`, `item_count`,
`subject_fingerprint`, `approval_url`, `action_review_proposal_id`, and an
`action_review` object with the Action Review proposal status, digest, whether
the card was sent, and whether the item was renewed. When `for_bundle` is
`true`, `action_review` and `action_review_proposal_id` are `null`; the bundle
creates the approval request. Otherwise, a mint failure is reported
inside `action_review` beside the staged package; it does not discard the
package. A ledger failure sets `unavailable: true`, gives a safe message, and
can be retried. If insertion succeeded but read-back failed, `action_review` still
names the request with `proposal_id` when known and `status: null`; retry to read its
state. During replay checks, a ledger failure remains `unavailable`, while a defect
checking an existing request sets `fault: true`; its detail is in the server log and
retry will not cure it. An audited derivation refusal sets
`refused: true` and includes `audit_reference`; only typed
`ProjectionDriftError` or `ValueError` causes are shown, while other causes are
logged and replaced with a generic refusal. SQL and driver error text is not
returned to the agent. The response also includes a `coverage` block containing
`proposed_here`,
`exhibited`, `dispositioned`, and `undispositioned` counts. The coverage is
measured when the package is staged and is returned unchanged on an idempotent
Prover replay, so its denominator is the original comparison state.
The optional `open_package_conflicts` response array lists each conflicting package's
`package_id`, `diff_hash`, and `item_count`; see the linked API reference for the
staging behavior and package-item details.
Staging conflicts involving a claimed correspondence rule are described in the
[disposition package API reference](/docs/Genesis-API/API-Reference#post-api-estate-comparison-events-diff_hash-disposition-packages),
which also defines the HTTP response's `expansion` metadata and corrective-selector refusal.
If the comparison or any item is
invalid, the tool returns `success: false` and an `error` without staging the
package. If the finding changes before approval, the reviewer must stage a fresh
package. Use `disposition_system_diff_finding` for a single finding you are
certain about; use the package tool when a human should review several proposed
diagnoses, including waivers.

Only one open `initial` package can stand for a comparison in the public review
lifecycle. A second proposal returns `success: false` with `open_package_ids` and
`standing_package`; read or finish the named package, or withdraw it with
`retract_finding_disposition_package`, before proposing again. `corrective` packages
are not blocked by this rule.

For a package containing `promote_pi`, staging runs the approval preflight before
writing the package. If any lasting rule cannot be approved — for example, its
fixtures fail, its approval for this pair was revoked, its evidence does not survive
the pair's configurations, or it does not license the finding — the whole proposal
is refused. The tool returns `success: false`, an `error`, and `refused_items` with
each `finding_key`, its finding `locus`, the approval `reason`, and `plain_reason`;
unbound promotions may also include `unbound_promotions` with qualified-rule advice.
Nothing is staged, so remove or correct the named items before proposing again.

The promotion preview used by Human Review applies the same preflight and reports
unapprovable items in `unavailable` with `reason` and `plain_reason`, rather than
showing them as licences. A previewed rule also includes
`plain_reusability_refusal` when the reviewer cannot approve it, including when its
approval on this estate pair was revoked. Qualification that requires running
against the comparison pair's environment remains checked during approval. If
approval derives and registers a rule, retries and repeated clicks reuse the
content-addressed rule and do not append a duplicate review-log audit event.

For reviewer-derived value-rendering and type-correspondence rules, the
applicability boundary must name the same object and column as the finding's
evidence using exact identifier text. Differences in case or whitespace are
not treated as the same element; re-propose the rule from the finding so both
fields are generated from the same rendering.

In a Prover finding or issue-group chat, `input_metadata.prover_context` is the
authoritative captured subject. The package must include exactly the captured
members, use `instrument_defect`, and match the current comparison ledger and
review population; malformed, stale, incomplete, or changed evidence is refused
without staging. A successful Prover-bound response also includes
`evidence_fingerprint`, `evidence_summary`, `evidence_scope`,
`evidence_member_count`, `idempotent_replay`, and `remeasurement: "not_enqueued"`.
The same source message returns the existing package with `idempotent_replay:
true`; changed package content requires a new message. Human approval remains
required, and only a fresh comparison can discharge the Prover finding.

For an existing diagnosis that needs replacement, use
`propose_finding_disposition_correction` instead; its approval page shows the
recorded and proposed verdicts.

### `propose_finding_disposition_correction`

Stage an agent's proposed replacements for diagnoses that are already recorded.
This is the corrective counterpart to `propose_finding_disposition_package`:
staging writes no findings, and the returned `approval_url` opens a Human Review
package that a reviewer approves or declines exactly as staged, as a whole; if any
replacement is wrong, they decline it and ask for a corrected package. Read
`list_finding_dispositions` first so every item has an existing diagnosis and the
new diagnosis is different. The package records the prior verdict for audit, and
approval returns the old-to-new `corrections`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Content hash of the comparison whose findings are being corrected. |
| `title` | string | none | Short summary of what is being corrected and why; maximum `200` characters. |
| `justification` | string | `null` | Plain-business-English case for replacing the recorded diagnoses; maximum `4000` characters. |
| `proposer_display_name` | string | `null` | Unverified readable label for the proposing agent; maximum `200` characters. |
| `items` | array of objects | none | One object per finding with required `finding_key` and the new `disposition`, plus optional `plain_summary` and `note`; a finding may appear only once. |
| `source_message_id` | string | implicit | Source user-message id from the active Prover chat; used with the thread id to make retries of the same request idempotent. |
| `input_metadata` | object | implicit | Active message metadata. When it contains authoritative `prover_context`, the corrective package is bound to the captured comparison, scope, and member identities. |

The new `disposition` must be one of `target_defect`, `source_drift`,
`promote_pi`, `promote_delta`, `spec_defect`, `instrument_defect`, or `waived`, and must differ
from the finding's current diagnosis. The package must contain at least one and
at most `2000` items, each most recently exhibited by `diff_hash`. The tool
refuses an undiagnosed finding, an unchanged proposed diagnosis, duplicate or
unknown findings, and invalid comparisons without staging anything. Nothing
changes until the request is approved, by a person or by an agent using
`decide_approval_request` for that person. A corrective package cannot be
unsigned; correct it again with another corrective package instead.

In a Prover finding or issue-group chat, authoritative `prover_context` binds the
correction to the captured comparison and member set. The tool accepts only the
`instrument_defect` replacement, refuses malformed or stale evidence and changed
membership, and returns the same evidence and idempotent-replay fields as the
initial package tool. It never enqueues remeasurement; a fresh comparison is
required after approval to discharge the Prover finding.

### `retract_finding_disposition_package`

Withdraw a disposition package you staged when nobody has ruled on it yet. This
removes the request from the reviewer's waiting list without changing any finding
disposition. You can withdraw only a package proposed under your own bot identity;
packages with an existing approval or rejection cannot be withdrawn, and an
already-withdrawn package cannot be withdrawn again. A `reason` is required and
must explain in one sentence what you got wrong or what changed; a blank reason is
rejected. Read the returned `error` for the reason instead of retrying. See the
[disposition package API reference](/docs/Genesis-API/API-Reference#estate-endpoints)
for the corresponding HTTP endpoint and response details.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Content hash of the comparison the package was staged against. |
| `package_id` | string | none | Package id returned by `propose_finding_disposition_package`. |
| `reason` | string | none | Required one-sentence explanation recorded in the review log; say what you got wrong or what changed, not merely that you are withdrawing it. |

The tool returns `success`, `package_id`, `diff_hash`, `status: "retracted"`,
`retracted_by`, `retracted_as: "proposer"`, `reason`, and `item_count`. A missing
bot identity fails closed rather than allowing an unattributed caller to withdraw
another package. This tool records proposer withdrawals only; when a person
declines or policy denies the package's linked Action Review request, the review
workflow closes the package as `retracted` with `retracted_as` set to
`"declined_in_action_review"` or `"policy_denied_in_action_review"`, respectively.

### `list_finding_disposition_packages`

List the disposition packages already staged for one comparison, newest first.
Use this before staging another package to find work already handed to a human
or to recover a package whose approval link was lost. Each row is a summary with
`package_id`, title, status, and item count; use
`read_proposal` to read its proposals and evidence.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Required content hash of the comparison whose packages should be listed. |
| `status` | string | `null` | Optional exact filter: `open`, `closed`, or `retracted`. Omit it to list every package on the comparison. |

The comparison is checked against the visibility of the person the agent is working
for before packages are read. A comparison they cannot open is answered as unknown,
without exposing its packages. The visibility check costs one scope load (four index
reads) before the package read.

The response reports `viewer_can_sign: false` and
`viewer_cannot_sign_reason: "no_signing_identity"` for every row because agents
do not hold a signing identity. Each row also includes `approval_url`,
`approval_generation`, and the current `action_review` head when an Action
Review item owns that package generation. Give a person the package URL, not
the generic Action Review tab; the Prover page is where this package is
decided. A package closed after a person declines or policy denies its Action
Review request appears with `status: "retracted"` and the matching
`retracted_as` value; the comparison is then available for a new package. An
unrecognized status returns `success: false` instead of an empty
list. An empty `packages` list means nothing has been staged for that
comparison; use `propose_finding_disposition_package` to stage a diagnosis
batch.

### `list_packages`

List every disposition package staged for a comparison and the counts by status.
Use this to find package IDs and check whether anything is still open before
proposing another package. Unlike `list_finding_disposition_packages`, this read
always includes every status so `counts.open` is a complete count; use
`read_proposal` to inspect one package's proposals and evidence.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | `""` | Required comparison hash. An unambiguous prefix of at least eight characters is accepted. |

The response includes `packages` newest first, `counts` (`open`, `closed`,
`retracted`, and `total`), and `open_package_ids`. Each package row includes
`viewer_can_sign` and `viewer_cannot_sign_reason`; these describe the signed-in
caller, not the agent's borrowed visibility. Open package rows include their
approval URL. The comparison is checked against the visibility of the person the
agent is working for before packages are read. A hidden comparison is answered as
unknown. This read includes approval-item state and page links for every package;
it reads no per-item finding evidence, which is loaded by `read_proposal` one
package at a time. It reads the comparison's review log, folds each package's
status, reads the Action Review link and status for each request, and loads the
page-address cache; it does not query per-item evidence.

### `read_proposal`

Read one staged disposition package and its decision status, including its
proposals and the finding evidence currently held by the ledger. Use this to
inspect what a package contains before reporting it as ready for review; use
`list_finding_disposition_packages` to find package IDs.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | `""` | Required content hash of the comparison where the package was staged. |
| `package_id` | string | `""` | Required package identifier from `list_finding_disposition_packages` or `propose_finding_disposition_package`. |

If the comparison has no package with that ID, the tool returns
`success: false`; the package may belong to another comparison or may have
been retracted. A successful response includes `approval_url`,
`approval_generation`, and `action_review` when an Action Review request owns
the package's current generation. The approval URL opens the package's own
Prover page, and the conversation also renders its decision card when the
package is open. A package staged with `for_bundle: true` has no individual
request; carry it with `propose_approval_bundle` to create the one request, or
use the package page's **Ask for approval** action if it should be reviewed alone.

### `read_bundles`

List the approval bundles still waiting on a comparison, or read one waiting
bundle with its full rationale and members. Use the list before reporting what
needs sign-off; pass a bundle ID to inspect its rule IDs, package finding keys,
and evidence-gap members. Only waiting bundles appear. Reading does not approve
anything; give the person the returned `action_review.url`, or `approval_url`
when the bundle has no Action Review request.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | `""` | Required comparison hash. An unambiguous prefix of at least eight characters is accepted. |
| `bundle_id` | string | `""` | Optional bundle ID. Omit it to list all waiting bundles; supply it to read one in full. |

For example, list waiting bundles with `read_bundles(diff_hash="a1b2c3d4")`.
The list includes each bundle's brief, proposer, timestamp, carried-member counts,
and Action Review request details. The comparison is checked against the visibility
of the person the agent is working for before bundles are read; a hidden comparison
is answered as unknown. The read costs one review-log read and may also plan
evidence-gap populations when a waiting bundle carries gaps. Each returned bundle
also reads its Action Review link and current request status.

### `record_review_decision`

Record a run-level verdict on a comparison when the person in the conversation asks you
to sign it off or reset it, or when the verdict is part of a goal, Blueprint, or mission
they set. The record identifies the agent and person and carries the approval basis. This
is not needed when the comparison is already **Verified** with nothing left to decide;
read `data.review.nothing_to_decide` from `read_comparison` first.

| Parameter | Type | Default | Required | Description |
| - | - | - | - | - |
| `diff_hash` | string | `""` | Yes | Comparison to record the verdict against. |
| `decision` | string | `""` | Yes | `awaiting_review`, `approved`, or `approved_with_exceptions`. |
| `approval_basis` | string | `""` | Yes | `agent_person_present` when the person in this conversation asked for the verdict; `agent_delegated` when it is part of a goal, Blueprint, or mission they set. |
| `authority` | string | `""` | No | Optional free text stating who authorised the decision, recorded beside the identity and basis. |
| `grading_run_id` | string | `""` | No | Grading run the approval is bound to. A mismatch refuses rather than approving a changed population. |
| `population_hash` | string | `""` | No | Hash of the reviewed population, bound to the approval as an optimistic-concurrency check. |

The person must be able to see the comparison. A missing or unknown `approval_basis`
refuses with `invalid`; when there is no person to act for, the tool refuses with
`unidentified`. `awaiting_review` records that the comparison is not approved. With
authentication disabled, the local operator remains the recorded identity. Resolving
the person requires up to two thread reads, one project read, and one users-table read;
recording the verdict reads and appends to the comparison review log. The returned
folded review state includes `decision_approval_basis`.

### `decide_approval_request`

Approve or reject a Prover approval request on a person's behalf when they ask in this
conversation, or when deciding it is part of a goal, Blueprint, or mission they set. It
covers Prover requests for disposition packages, bundles, proposed rules and mappings,
seat rulings, evidence requests, and test cases. Other Action Review requests are not
eligible. An approval applies its requested change immediately; a rejection records the
decision and applies nothing.

| Parameter | Type | Default | Required | Description |
| - | - | - | - | - |
| `proposal_id` | string | `""` | Yes | `ap_`-prefixed request id from `action_review.proposal_id`, `action_review_proposal_id`, or a `list_action_reviews` row. |
| `decision` | string | `""` | Yes | `approve` or `reject`. |
| `approval_basis` | string | `""` | Yes | `agent_person_present` when the person in this conversation asked for the decision; `agent_delegated` when it is part of a goal, Blueprint, or mission they set. |
| `reason` | string | `""` | No | Optional plain-language reason recorded with the decision and shown to readers. |

The person must be able to see the request's subject. With authentication disabled,
`approval_basis` is still required and the decision is recorded as
`local operator (auth disabled)`. A request that is not a Prover request is refused with
`human_authority`; a request outside the person's visibility is
reported as not found. A missing or unknown `approval_basis` refuses with `invalid`, and
a turn with no person to act for refuses with `unidentified`. An agent may decide its own
request; the record names the agent as both requester and decider.

For example, to approve a package the person asked you to accept:

```python theme={null}
decide_approval_request(
    proposal_id="ap_example",
    decision="approve",
    approval_basis="agent_person_present",
)
```

The response includes `decided`, `success`, `final_status`, `refusal_reason`,
`execution_refusal_reason`, and the proposal status, including `decided_by_label`.
Resolving the person costs up to two thread reads, one project read, and one users-table
read. The decision also reads the proposal and its subject's visibility, loads policy,
and records the decision; approval runs the request's application work.

### `propose_approval_bundle`

Stage a single approval bundle for a comparison. The bundle can carry
the three review-queue populations together: correspondence-rule proposals,
disposition packages staged earlier with `propose_finding_disposition_package`
(prefer `for_bundle: true` when staging them for this request), and evidence-gap
exception packages. Staging changes none of them. When the
response includes `action_review`, send its `url` to the person; otherwise use
`approval_url` or, when it is `null`, `approval_path`. The agent that proposed
the bundle may decide its request for the person when asked or when it is part of a goal
they set, using `decide_approval_request`.

Use `rule_ids` or `all_proposed_rules` for correspondence rules, and use
`evidence_gap_package_ids` or `all_open_evidence_gaps` for evidence gaps, never
both forms for the same kind. `package_ids` names already-open disposition
packages and does not amend them. A bundle must contain at least one member.
For partial-seal open-clause packages, use the [bundle API contract](/docs/Genesis-API/API-Reference)
for the bulk-selection exception and explicit package-id behavior.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `diff_hash` | string | none | Content hash of the comparison whose review queue is being handed to a human. |
| `rationale` | string | none | One reason for approving the whole bundle, in the reviewer's language; maximum `4000` characters. |
| `brief` | object or null | `null` | Optional short account shown first on the Action Review request. When supplied, all four fields are required: `title` (1–120 characters), `proposal` (1–400), `why` (1–400), and `weigh` (1–4 non-empty statements, each 1–200 characters). No other field, including a recommendation, is accepted. |
| `rule_ids` | string\[] | `[]` | Correspondence proposal ids to carry. Use this or `all_proposed_rules`, never both. |
| `all_proposed_rules` | boolean | `false` | Carry every open correspondence proposal offered by this comparison. |
| `package_ids` | string\[] | `[]` | Open disposition package ids to carry as proposed. Stage packages with `for_bundle: true` to avoid creating a separate request before this bundle. |
| `evidence_gap_package_ids` | string\[] | `[]` | Evidence-gap exception package ids to carry. Use this or `all_open_evidence_gaps`, never both. |
| `all_open_evidence_gaps` | boolean | `false` | Carry every evidence-gap package that still has an open member; this is the usual form because agents cannot enumerate those package ids first. |
| `evidence_gap_waiver_owner` | string | `null` | Owner recorded for accepted evidence-gap exceptions. Defaults to the approving person. |
| `evidence_gap_waiver_expires_at` | string | `null` | Future ISO-8601 expiry recorded for accepted evidence-gap exceptions; required when the bundle carries any evidence-gap package. |

The response includes `bundle_id`, `approval_route`, `approval_url`, and `carries`,
which reports counts against their source populations: proposed rules,
undispositioned findings, and open evidence-gap members. See the
[Estate API reference](/docs/Genesis-API/API-Reference#estate-endpoints) for
route meanings and when `action_review` is returned. Relay `carries.excluded_rules` too.
When supplied, `brief` is also returned with the bundle and shown before its full
`rationale` on the Action Review request. Keep the brief in plain language and
write `proposal` and `why` in at most three sentences each, as requested by the
tool; write `weigh` as the uncertainties a person should consider. For example:
`brief={"title":"Approve the customer ID mapping","proposal":"Record the matching ID on the customer table.","why":"The comparison found a consistent mapping.","weigh":["The sample may not cover every customer.","The source key may not be unique."]}`.
A missing part, a part over its limit, or an extra field is refused rather than
shortened. Re-proposing the same standing bundle does not replace its brief. See
[Prover review guidance](/docs/Genesis-Prover/Roles-And-Approvals#approve-one-review-bundle)
for what the person sees and what the decision attests to.
The defaults eligibility predicate excludes rules whose subject is a statistic
derived from measured values; each excluded row gives the rule and its reason.
`all_proposed_rules` never sweeps in a data-derived or unclassified rule. An agent
may carry one only by naming it in `rule_ids` and proposing a rules-only bundle;
the human's Action Review request shows the rule's sealed evidence. See the
[Prover review guidance](/docs/Genesis-Prover/Roles-And-Approvals#approve-one-review-bundle)
for what the reviewer sees.

The bundle records the comparison run and population scope at proposal time.
If the same proposer retries with the same membership and scope, the tool
replays the standing bundle instead of creating a duplicate. If a package or
evidence-gap membership changes before approval, the human must receive a fresh
bundle. For details, see the [Prover review guidance](/docs/Genesis-Prover/Roles-And-Approvals#approve-one-review-bundle).
The human signs through the linked Action Review request when it is
present, or the bundle's API review surface otherwise; no Prover tool can sign
it. On an authentication-disabled deployment, the human review doors
accept an optional `X-Genesis-Signed-As` header and disclose that self-reported
name in the stored signer label; see the [Estate API reference](/docs/Genesis-API/API-Reference#estate-endpoints)
for the shared signer rule. For ratified rules without attached evidence, the request
names the component pair and licensed object or column; see [Prover roles and approvals](/docs/Genesis-Prover/Roles-And-Approvals#approve-one-review-bundle)
for the full reviewer explanation. While that request is live, the carried rules cannot
be signed off separately; the same page explains how a live request on another
bundle blocks approval of a shared rule.
When a person rejects that request, eligible carried agent- or service-proposed
rules are withdrawn from the comparison; see the Prover guidance for the
comparison scope, reversibility, and exceptions.

An agent may name at most one data-derived or unclassified rule in a rules-only
bundle, which uses Action Review. Do not include disposition packages or evidence-gap
packages with it, and do not use `all_proposed_rules` to select it. Naming more than
one is refused with `one_data_derived_rule_per_bundle`; combining one with other
members is refused with `data_derived_rule_needs_a_rules_only_bundle`. A person
naming such a rule is refused; the rule's own Action Review request is its approval
path.

Other agent bundles that combine Action Review-only correspondence rules with
evidence-gap packages but no disposition package are refused with
`agent_rules_need_their_own_bundle`; submit those rules and evidence gaps separately.

When an agent bundles a disposition package it staged earlier with
`propose_finding_disposition_package`, the bundle adopts that package's pending
Action Review request if the same agent asked for it on behalf of the same
human. The earlier request is withdrawn and the composite bundle request
replaces it; `data.action_review.adopted_package_requests` lists the withdrawn
proposal IDs. If a member request belongs to someone else, was already decided,
is carried by another bundle, has no conversation-thread origin, or is denied
by package policy, the whole bundle is refused before staging. A request made
without a conversation thread—for example, when a person selects **Ask for
approval again** on the package page—cannot be taken over by the bundle and is
reviewed on its own. Check
`refusal.detail.rule`: `package_approval_owned`, `package_approval_decided`,
`package_in_other_bundle`, `package_policy_denied`, or
`package_request_not_adoptable`; leave that package out and propose again. If
creating the composite request fails before it exists after adoption, the freshly staged
bundle is withdrawn and the error reports `withdrawn_package_requests` and
`bundle_retracted`; the member packages can then be asked for again or included in a new
bundle. If insertion succeeds but reading the composite back fails, the bundle remains
staged (`bundle_retracted: false`), and the unavailable result names its `proposal_id`
when known and lists the adopted IDs in `withdrawn_package_requests`. Repeat the same
proposal to read the existing request; do not stage a duplicate.

### `evaluate_estate_correspondence_rule`

Report whether a proposed **estate** correspondence rule passes its own accept
and reject fixtures before handing it to a human. This is a report-only check:
it records no qualification evidence, advances no provenance tier, and cannot
ratify the rule. For transition-contract artifacts, use
`qualify_transition_contract_rule` instead.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `rule_id` | string | none | Required content-addressed id of a proposed estate rule returned by `propose_rename_correspondence` or `propose_correspondence_rules`. |
| `diff_hash` | string | `""` | Optional system-diff hash for the comparison the human should review. |

The response includes `fixtures_pass`, `fixture_count`, `failed`,
`untested_claims`, per-fixture `results`, the rule's current `provenance`, and
`qualification_recorded: false`. `fixtures_pass` is `true` only when every
fixture passes and every claim has a boundary fixture; `failed` counts fixtures
that did not hold, while `untested_claims` names claims that have no boundary of
their own. This distinguishes a rule with a failing fixture from one whose
fixtures pass but do not exercise all of its claims. It also returns
`ratification_url` and `actionable`; when `diff_hash` is omitted, `actionable`
is `false` and `blocked_by` explains that the worklist controls are disabled
until a comparison is pinned. This tool evaluates only estate rules; an
artifact hash from the transition-contract registry is refused as the wrong
identifier family.

Stimulus design and compile run summaries disclose the schema-gate evidence in
`schema_validated`, `schema_validation`, and `measurement_incomplete_objects`.
The gate runs only when the boundary snapshot has complete catalog enumeration.
An indeterminate object still contributes its catalog column names when the
snapshot was produced by measurement library version 7 or later; older
indeterminate snapshots require re-characterization and report
`skipped_legacy_indeterminate_snapshot`. Other possible `schema_validation`
values are `validated`, `validated_incomplete_measurements`,
`skipped_incomplete_enumeration`, and `skipped_no_schema`. When the gate is
skipped, structural validation remains active, but table or column absence is
not mechanically validated.

### `register_execution_profile`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `profile_id` | string | — | Stable id for the estate execution profile. |
| `kind` | string | — | Adapter kind: `postgres_dbt`, `databricks_sql`, `databricks_notebook_sql`, `snowflake_sql`, `clickhouse_sql`, `mssql_sql`, `bigquery_sql`, `sqlite_sql`, `csv_sql`, `file_python_oracle`, `databricks_repo_sql`, or `databricks_job`. |
| `connection_ref` | string | — | Connection id whose credentials the adapter resolves. |
| `payload` | object | — | Adapter metadata only; required fields depend on `kind`. |
| `boundary_hash` | string | `""` | Optional boundary hash tying the profile to its stimulus scope. |

On success, the tool returns `success`, `profile_id`, and `created_by`. The
`created_by` value is the identity recorded on the profile, which stays the first
registrant's. The response also includes `attributed_to_another`: `false` when the stored
creator is the caller, and `null` when the record names nobody. A missing caller or a
record with no named creator is returned as `created_by: "unattributed"`; do not describe
that profile as belonging to the caller.

A profile recorded under a registrant is registered over by that registrant only. A call
by anyone else for the same `profile_id` returns `success: false` with
`error_kind: "profile_registered_by_another"` (or
`"prepared_profile_registered_by_another"` for a profile `prepare_migration_prover`
registered), names the registrant, and stores nothing, whatever the call would change.
Register the profile under a new `profile_id` instead. A profile whose record names nobody
can be registered over by any caller, unless `prepare_migration_prover` registered it.

During validation, an island table name may be bare, schema-qualified
(`schema.table`), or database-qualified (`database.schema.table`). Qualified
names retain every segment for both island-row counting and cleanup. Names with
more than three segments are not addressed.

For `postgres_dbt`, `payload.dbt_env` maps environment variable names to literal
values or templates using `{host}`, `{port}`, `{user}`, `{password}`, and
`{dbname}`. Genesis fills those placeholders from the source connection and
sandbox database. Profile setup refuses any other placeholder before saving;
the adapter also checks persisted profiles before a run. Write other values
literally, and double braces (`{{` and `}}`) when the value needs literal
braces. During stimulus replay, a row that supplies a value for a
`GENERATED ALWAYS` identity column is inserted with that value. Genesis advances
the identity sequence to that value when it is at or beyond the next sequence
value and within the sequence maximum; otherwise the sequence is unchanged.
Rows that omit the identity value continue to use the generated value.

For `csv_sql`, the payload requires `repo_id`, `csv_files` (a non-empty string
map), and `transform_sql` (a non-empty string map). For
`databricks_repo_sql`, it requires `catalog`, `sandbox_catalog`, `repo_id`,
`source_tables` (a non-empty string-array map), and `model_sql_files` (a map of
non-empty strings or non-empty string arrays). Optional `table_map` values must
be `schema.table` names declared in `source_tables`. The optional
`managed_location` payload value is an explicit mission override; when it is
omitted, the guarded adapter can use the target Databricks connection's
non-secret `prover_managed_location_root` for the sandbox catalog.

For `databricks_job`, the payload is target-only and requires `job_id` (a
positive integer), `job_hash_contract_version` (currently
`estatechar.databricks_job.settings.v1`), `job_settings_sha256`, `run_as`,
`deployed_assets` (an absolute Workspace notebook path to SHA-256 map),
`landing`, `input_files`, `parameter_bindings`, `task_dependencies`, and
`task_outputs`. `run_as` names exactly one `service_principal_name` or
`user_name`. The landing scheme must be `databricks_volume`.

The optional `mode` is `selective` or `monolithic`; an omitted mode remains
`selective` for compatibility with existing profiles. Selective mode is the
purpose-built harness contract. It also requires `output_catalog` and
`output_schema`, which must match the landing catalog and schema, and requires
exactly five distinct parameter bindings: `landing_path`, `output_catalog`,
`output_schema`, `campaign_token`, and `requested_models`. The adapter sends
`requested_models` as a compact JSON array encoded in a Job parameter string,
for example `["dim_customer","fct_order"]`, and reads token-prefixed output
tables.

Monolithic mode runs the customer's complete existing Job DAG with normal fixed
output names. It requires exactly the three generic bindings `landing_path`,
`output_catalog`, and `output_schema`; Genesis never sends `campaign_token` or
`requested_models` to the Job. The shipped Job must already expose those generic
locations. A Job with hard-coded input or output locations, including a Job with
no parameters, is not supported. The pipeline must rebuild its outputs from the
staged input; pipelines requiring pre-existing target state need a different
execution contract. `fixed_output_tables` must map every logical
model in the union of `task_outputs` to a unique, safe, unqualified physical
table name. Monolithic profiles must not provide the selective-only
`output_catalog` or `output_schema` fields. The output catalog comes from
`landing.catalog`; `landing.schema` must match `<base>_(stim|eval)` with an
optional `_<suffix>` so Genesis can derive and guard a unique campaign-owned
schema.

The profile runs an already-deployed multi-task Job rather than uploading or
rewriting it. Before provisioning and again before submission, Genesis verifies
the pinned execution-affecting Job definition, the declared Workspace notebook
hashes, the static `%run` dependency graph, the task DAG, and the required Job
parameter bindings. Selective mode retains its existing rule that every task and
task notebook consumes every binding. In monolithic mode, root tasks must consume
`landing_path`, tasks owning declared outputs must consume `output_catalog` and
`output_schema`, and the task and asset unions must cover all three roles. Other
tasks, such as downstream quality or notification tasks, need not reference
parameters they do not use. Every target model must appear in exactly one
`task_outputs` entry, and task dependencies must form an acyclic graph.

Monolithic v1 accepts only one consolidated stimulus group and no ordered
groups. Genesis refuses any other plan before provisioning because a complete
rebuild applies cumulative landing rows to every candidate output while the
selective source oracle's terminal per-output baselines come from different
steps. Comparing those states under terminal collapse would create false
failures. Each accepted run executes the full declared DAG, regardless of the
logical models named by the planner, and records `planned_models` with
`execution_scope: all_declared_outputs`.

For monolithic isolation, Genesis acquires a unique schema with `CREATE SCHEMA`
without `IF NOT EXISTS`, records ownership only after creation succeeds, and
passes the campaign landing path, catalog, and owned schema through the generic
bindings. A collision therefore fails rather than assuming ownership of an
existing schema. Successful teardown drops only the recorded owned schema with
`CASCADE`; a failed submitted campaign retains that schema and its landing for
diagnosis. Teardown never drops a schema whose acquisition was not recorded. If
submission never occurred, an acquired empty schema can be removed safely.

A run is accepted only when the pinned Job and every task finish successfully
with complete output evidence; failed, incomplete, or unverified runs are not
accepted as migration proof. Observations remain keyed by logical model and
record both the logical `relation` and the physical isolated
`execution_relation`. Models without a stimulus specification are listed in
`unobserved_declared_outputs` rather than presented as validated.

A monolithic verdict proves the approved shipped Job settings, identity, and
Workspace assets ran unchanged over redirected generic locations. It does not
cover production table instances, production storage permissions, undeclared
outputs or side effects, hard-coded checkpoints or locations, external-system
writes, shared filesystem paths, schedules or overlapping non-Prover runs,
unsupported task types, or dynamic notebook launches. Every planner execution
runs the complete DAG, so this mode can cost substantially more than selective
execution. The connection principal also needs Job execution, Workspace export,
Volume access, SQL read, `USE CATALOG`, `CREATE SCHEMA`, and schema-drop
privileges in the sandbox catalog. Failed campaign schemas may contain all
pipeline outputs and can therefore have material retention cost. Jobs whose
definition or run-evidence arrays exceed the Databricks 100-element response page
are not supported until Genesis aggregates Jobs API 2.2 pagination for both Get
Job and Get Run.

To author a `databricks_job` profile without guessing the pinned values, call
`preflight_databricks_job_contract` with the deployed `job_id` and its stored
`connection_ref` first. Copy its `job_settings_sha256`,
`job_hash_contract_version`, canonical `run_as`, and `parameter_formats` into the
profile. The returned parameter formats describe the five required semantic roles:
`landing_path` is the staged Databricks Volume URI, `output_catalog` and
`output_schema` identify campaign-owned outputs, `campaign_token` qualifies the
campaign's outputs, and `requested_models` must receive a compact JSON-encoded
array string such as `["model_a","model_b"]`, not comma-separated values. If the
Job has no explicit `run_as`, the response returns `run_as_absent` and an instruction
to set one before preflighting again. If its live identity cannot be represented by
the profile's single `service_principal_name` or `user_name`, the response returns
`run_as_unpinnable` and explains the required correction. Set
`include_projection` to `true` only when the full canonical settings projection is
needed for review; its default is `false`.

The failed-campaign retention record reports what teardown verifies, not only
what the campaign intended to create. The landing record includes
`status: "retained"` when the campaign-owned Volume path contains a staged
file, or `status: "absent"` when it does not; nested landing directories are
checked as needed. The output record includes a `relations` map whose values
are `"retained"` or `"absent"` for each targeted output relation. If a landing
or output verification probe fails, the record includes `verification_error`
instead of claiming that the resource is absent. Output verification checks
the expected relations together in one catalog query: targeted token-prefixed
relations in selective mode, and every declared fixed output in monolithic mode.

For `snowflake_sql`, a repository-backed target can replace `deployed_sql` with
`repo_id`, `model_sql_files`, `table_map`, and `target_grains`. The four fields
are required together, and the payload must not include `deployed_sql`. Each
target model must name exactly one repository-relative UTF-8 SQL file containing
one self-contained Snowflake `SELECT` query; paths must remain inside the Mission
repository. `table_map` maps each onboarding stimulus input to a
`schema.table` base table, and `target_grains` declares the ordered key columns
for each target model.

For repository-backed Snowflake targets, `table_map` values and
`target_grains` columns resolve against Snowflake's stored relation and column
names: an exact spelling wins; otherwise the plan name must match exactly one
stored name after folding ASCII letters only. Missing or ambiguous matches
refuse validation. This lets a PostgreSQL plan's lowercase unquoted names
resolve to Snowflake's uppercase unquoted names without treating non-ASCII
look-alikes as the same identifier. In dbt-backed Snowflake execution, the same
rule applies to stimulus column names.

Before cloning the target, Genesis reads the live target columns and primary-key
metadata and checks that every declared grain exists, matches an existing
primary key when one is present, and is unique and non-null in the live data.
During execution, the adapter loads stimulus rows into the declared source
tables, retargets the reviewed repository SQL into the campaign sandbox, and
records the SHA-256 of each SQL file actually executed. The adapter also returns
the observed live target metadata in execution evidence; onboarding validation
rejects a run when required execution evidence is empty.

For `mssql_sql`, the payload requires `database` and `sandbox_prefix`. This
source-only adapter supports SQL Server 2022 (major version `16`) on Linux and
requires a `sysadmin` connection using the ODBC driver (`pyodbc`). SQL Server
connections made inside a Databricks App use `pymssql` and cannot run this
sandbox adapter. During each validation run it takes an
on-instance `COPY_ONLY` backup and restores it into a generated sandbox database
whose name starts with `sandbox_prefix`; the live database is not used for
writes. The adapter tears down the generated database and backup resources when
the run finishes.

For `bigquery_sql`, the payload requires `project`, `dataset`, and
`sandbox_prefix`; it optionally accepts `deployed_sql`, a string map of model
names to deployed query text for materialized targets. The
`connection_ref` must resolve a BigQuery connection whose project matches
`project`. This source-only adapter preflights the configured dataset, creates
an owned per-run sandbox dataset whose name starts with `sandbox_prefix`, and
clones its tables while recreating logical views with references retargeted to
the sandbox. Materialized targets use their `deployed_sql` in the sandbox;
logical views re-derive from the cloned source objects. Stimulus rows are
inserted only into tables declared by the source descriptor's `schema_columns`
(using `dataset.table` names). Use `bigquery_sql` only as `source_profile`, not
as `target_profile`. The live dataset is not written, and the owned sandbox
dataset is deleted when the run finishes.

For `snowflake_sql`, the payload uses `database` for the live database and an
optional `sandbox_database` as the guarded sandbox base. When omitted,
`sandbox_database` defaults to a derived base such as `<database>_STIM`; each
validation run appends an uppercase random hexadecimal suffix to create its own
throwaway zero-copy clone. Target views and their upstream view dependencies are
recreated from immediate `GET_DDL` metadata with fully qualified live-database
references rebound to the clone, so injected stimulus is visible to the views.
Cloned SQL UDFs that qualify the live database are likewise recreated with the
sandbox qualifier; their bodies are edited in place, so escaped literals in the
body are preserved. When a target view or dynamic table calls a cloned SQL or
JavaScript UDF, the purity check follows scalar UDF calls transitively; every
called UDF must be provably sandbox-local before validation proceeds.
The live database remains read-only. Provisioning fails closed for degraded view
definitions, external or dynamic object references, stage references, and other
dependencies whose sandbox locality cannot be proven.

For a view target, `table_map` can map the relation named in the stimulus spec
to its deployed Snowflake relation in the live database. For example,
`{"OLD_SCHEMA.V": "NEW_SCHEMA.V"}` lets a rewritten view sit beside the
original; the adapter validates and recreates `NEW_SCHEMA.V` in the sandbox.
When a Prover estate comparison uses this run to license the rewritten view, the
proof must match the compared source and target view pair; matching database sides
alone does not let a proof of another rewrite license it. See [fresh licensing
evidence](/docs/Genesis-Prover/Overview#fresh-licensing-evidence).
For repository-backed targets, `table_map` retains its separate role of mapping
stimulus inputs to declared base tables, as described above.

When both sides resolve a tested view to the same live object on the same
connection and database, preparation and validation runs refuse the pair and
name the view. Non-rehearsal trajectory campaigns refuse it too; rehearsals
intentionally skip this check because they run the source against a second copy
of itself. Map the rewritten view in the target's `table_map`, or point its
`database` at the one that holds the rewrite. A view is always rebuilt from its
own live definition, so a profile that gives a view `deployed_sql` is refused
when the run finds the object is a view; `deployed_sql` is for base tables only.

A view target may also read ordinary base tables from other databases when each
profile declares the needed tables in `source_tables` or `copied_tables`. Both
fields are optional maps of `DATABASE.SCHEMA` to non-empty arrays of table names,
using plain identifiers; the same table cannot be declared twice. These fields
are for view targets only and cannot be combined in that profile with
`deployed_sql` or `model_sql_files`. Only listed tables are provisioned. The
adapter creates a `<DATABASE>__<SCHEMA>` schema inside the sandbox database and
rewrites the view reference to that schema. It zero-copy clones `source_tables`;
use `copied_tables` for a base table that must be read and copied in full on each
run, such as a table exposed through a share. This full read and copy adds
per-run work proportional to the listed tables' data.

Only ordinary base tables are accepted under either field. Views, streams,
dynamic tables, Iceberg tables, and hybrid tables are refused. A view reference
to an undeclared external table, or a function call into another database, is
also refused. For stimulus cases that write one of these tables, name it by its
live three-part relation (`DATABASE.SCHEMA.TABLE`); each participating Snowflake
profile must declare the tables its rows use. A row must supply any column whose
default cannot be proven sandbox-safe, including a default that names a sequence
outside the sandbox. View definitions, dynamic tables, verified functions, and
`deployed_sql` queries that use `NEXTVAL` or `GETNEXTVAL` are refused, because
evaluating them would advance a sequence.

The optional `model_invocations` payload value is an object mapping each model
name to one non-empty T-SQL batch or an array of non-empty T-SQL batches. A
mutable base-table model must declare an invocation; a view model must not.
Each invocation must call a schema-qualified stored procedure copied from the
source database and is limited to orchestration SQL. It cannot use data-change
statements, dynamic SQL, transaction or session control, `GO`, external
cross-database references, or global temporary objects. In
`prepare_migration_prover`, the
source descriptor still requires `schema_columns` as described below, and
`mssql_sql` can only be supplied as `source_profile`, not `target_profile`.

### `preflight_databricks_job_contract`

Read the profile-ready execution contract from one deployed Databricks Job before
authoring a `databricks_job` target profile. This performs one or more Databricks
REST calls, depending on the number of Job response pages, and does not modify the
Job. The read follows the Jobs API 2.2 `next_page_token` until the complete Job is
available; an incomplete response is refused rather than hashed or pinned.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `job_id` | integer | — | Positive integer id of the deployed Databricks Job to inspect. |
| `connection_ref` | string | — | Stored Databricks connection reference used to read the Job. |
| `include_projection` | boolean | `false` | Return the full canonical settings projection when `true`; omit it for the compact profile-ready response. |

The response includes `job_settings_sha256`, `job_hash_contract_version`, and the
runtime `parameter_formats`. It returns a canonical `run_as` when the live Job
identity can be pinned by the profile contract. Otherwise it returns either
`run_as_absent` or `run_as_unpinnable`, together with an instruction for correcting
the Job and running the preflight again. Use the returned values when filling the
`databricks_job` payload described in [`register_execution_profile`](#register_execution_profile).

Example:

```python theme={null}
preflight_databricks_job_contract(
    job_id=12345,
    connection_ref="databricks-prod",
)
```

### `prepare_migration_prover`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `profile_scope` | string | — | Stable journey or mission scope, such as the root migration project or onboarding repository id. |
| `source_profile` | object | — | Exactly one adapter-keyed, credential-free source descriptor. |
| `target_profile` | object | — | Exactly one adapter-keyed, credential-free target descriptor. |
| `specs` | array | — | The `estatechar.stimulus_spec.v1` cases to run. |
| `user_approved` | boolean | — | Must be `true`; it does not itself approve the test cases. Ask for approval with `request_test_case_approval`; a person can decide in Action Review or an agent can use `decide_approval_request` on their behalf before a run uses the cases. |
| `component_pair` | string | `""` | Optional `<source-kind>-><target-kind>` label. |
| `migrator_id` | string | `""` | Optional migration agent or tool id. |
| `migration_scope_checksum` | string | `""` | Approved migration-scope checksum. Required when `pipeline_validation` is supplied. Copy it from the Mission inputs. |
| `pipeline_validation` | object or null | `null` | Optional reviewed pipeline contract. Requires lowercase SHA-256 `pipeline_checksum` and `conversion_checksum`, a non-empty distinct `output_models` string array, and explicit boolean `incremental` and `replay_no_new_input` choices. Both execution profiles must cover exactly those outputs. |
| `view_pairs` | array of objects | `null` | Optional original/rewritten view pairs to check the stored cases' coverage claims against. Each object requires `original` and `rewritten` (`SCHEMA.VIEW`); optionally provide `original_boundary_hash` and `rewritten_boundary_hash` for views scanned under another boundary. |

Each profile uses the tagged shape `{adapter_kind: {connection_ref, payload}}`.
Source payloads also require `schema_columns`, a non-empty map from logical
table names to non-empty arrays of non-empty column names. Each stimulus spec
requires `schema_version: "1"`, `spec_kind: "estatechar.stimulus_spec.v1"`,
`target_node`, `output_relation`, `stim_predicate`, and `cases`; each case
requires `case_id`, `rationale`, `tags`, and `rows`. A row's `table` must match
a declared `schema_columns` key. For a `csv_sql` source paired with a
`databricks_repo_sql` target, the target-node suffix must also exist in both the
source `transform_sql` map and target `model_sql_files` map. In that pairing,
each `output_relation` must be a `schema.table` string; the model keys in both
maps must remain the bare `target_node` suffix rather than a physical table name.

Case ids define stimulus-spec ownership. A spec's identity is its `target_node`
plus the set of its case ids, so multiple specs may target one node when they
cover different case sets. Case ids must be unique within a spec and cannot be
claimed by two different specs for the same target. Within one submission,
combine cases into one spec instead of submitting the same identity twice. To
re-author an existing spec, submit the same target and case ids; the new version
supersedes the previous one. Distinct identities remain stored and are all kept
in the effective boundary set.

If a stimulus batch includes machine-checkable `expected_target_deltas`, each
vector needs `mart`, `key`, `column`, and a scalar `target_expected`; use
`source_expected: null` for a target-only check. A vector defaults to
`value_basis: "absolute"` under a resolved contract only when the key columns
exactly match one declared input table's `entity_key` and every value is at or above
that table's inclusive island floor. Otherwise set `value_basis` explicitly to
`"absolute"` or `"delta"`; the vector is not checkable without it. Contract-less
shopbench behavior remains the legacy `id`-shaped-key rule with the reserved range
(`>= 900000`).

#### File-fed pipelines (`file_python_oracle`)

A pipeline driven by a batch of landing files, rather than by rows in a table,
uses the `file_python_oracle` source kind. Its payload declares `landing` (the
scratch location a batch is staged into), `input_files` and `declared_outputs`
(each a map of logical name to `{path, format, columns}`, with `types` also
required on outputs), and `oracle` — the reviewed program that executes the
transform, pinned by `sha256` so approval binds to an exact artifact rather
than to a repository path. `oracle.modules` pins every other repository file the
program may import, each by digest. Only the entrypoint and those modules are
staged into the campaign's own directory, and the subprocess runs from that copy
with `PYTHONPATH` pointing at it — so the approval covers the whole executable,
and importing an undeclared repository file fails rather than silently widening
what runs.

Two guarantees are structural rather than advisory. The `landing.prefix` must
carry a `stim` or `eval` marker, so a batch can never be staged into the
standing prefix a live pipeline already reads; and each run stages beneath its
own campaign-token directory. `validate_migration` then binds the target to the
sequence of landing manifests the source recorded, so a target whose staging is
not byte-identical fails before its transform runs.

Preparation also checks the PAIR, not only each profile: a file-fed source needs a target
kind that can bind a landing manifest, such as `databricks_job`, so pairing one with a
row-injecting target is answered `unsupported` rather than failing mid-campaign.

`oracle.assurance` is either `direct_runtime` or `reviewed_clone`. A reviewed
clone must also declare `stands_in_for`, naming the original system it stands
in for; the run record then carries an explicit limitation saying the campaign
does not cover that runtime. Only a `local_scratch` landing is stageable today.
A profile naming an object-storage or Unity Catalog volume landing is answered
with `status: "unsupported"` and the exact missing capability.

The preparation call fails closed for unsupported fields, invalid adapter
values, credential-like payload keys, missing metadata, mismatched CSV schema
keys, or missing models. It returns `status: "ready"` only when both profiles
pass the capability preflight; otherwise it returns `status: "unsupported"`
with `missing_capabilities` and persists nothing. On success, ask for the test
cases to be approved with `request_test_case_approval`, then pass the returned
profile ids to `validate_migration`; do not call it after a failed preparation
response.

Readiness also requires every submitted stimulus spec to be verified in storage
for the returned boundary. If the store contains fewer specs than were submitted,
the tool returns `success: false`, `ready_for_validation: false`, the `boundary_hash`,
and the `specs_registered` list instead of claiming readiness. A spec whose identical
content is already stored under a different boundary is rejected during the
submission check; change its content or reuse the boundary it belongs to. A ready
response includes `stored_spec_count` alongside `specs_registered`.

When `pipeline_validation` is supplied, preparation binds the reviewed pipeline
contract into the reusable source/target boundary. See [Pipeline migration
proofs](/docs/Genesis-Prover/How-A-Run-Works#pipeline-migration-proofs) for the
state-check semantics and verdict rules.

When preparation is ready, the response also includes `created_by`, mapping
`source_profile` and `target_profile` to the identities stored on those profiles, and
`attributed_to_another`. The latter is `true` if either profile names somebody else,
`false` if both name the caller, and `null` when neither names another person or a
profile creator could not be read back. A profile with no named creator is shown as
`"unattributed"`; use these fields when reporting who registered the profiles rather
than echoing the current caller.

When `view_pairs` is supplied, a ready response also includes each pair's claims summary
and fix suggestion, without view text or outlines. Claims are informational and do not
change preparation readiness; see [logic-path coverage claims](#logic-path-coverage-claims)
for the design and check-only workflow. A malformed pair is refused before preparation
stores any profiles or specs.

### `validate_migration`

Run the prepared behavioral migration proof with the same designed stimulus
cases against the source and target profiles. Both live estates remain
read-only; proof writes use throwaway sandboxes.

A run uses only test cases a person approved in Action Review.
`validate_migration`, `run_trajectory_campaign` and `qualify_stimulus_campaign`
check this once, when the run starts: if a view's test cases are not all approved
and unchanged, the run injects nothing and returns `success: false` with a
`refusal` that names the view and says what to do. A person with
`ratify_source_contract` approves them; with sign-in off they are approved at once
when the agent asks, and marked as not reviewed by a person.

The check compares the cases the run will fold with the complete current set for
that view and boundary. It also refuses when those cases disagree on their stored
output relation or condition, or when the run would mix boundaries or use cases
stored without one. A reused baseline that pins only some of a view's current cases
is refused too; approve the current set and run without `baseline_trace_hash` to
record a new baseline. The refusal has kind `test_cases_not_approved` and a reason:
`not_approved`, `outputs_disagree`, `not_current`, `other_boundary`,
`view_gained_test_cases`, `stored_without_boundary`, `approved_for_other_profiles`,
`approval_record_unreadable`, or `approval_not_finished` (an approval of the test cases
was started and is not recorded as finished; have it reconciled in Action Review).

Test cases prepared with `prepare_migration_prover` are approved for the source and
target profiles it registered. A run must use that source profile as its source and that
target profile as its target, each unchanged since the approval; any other profile is
refused with `approved_for_other_profiles`, even one on the same connection. After
preparing the same pair again with other settings, ask for approval of the same test
cases again with `request_test_case_approval`: the new request covers every prepared
profile standing for the pair and lists them.

Text stimulus values use the registered dialect's quoting rules for the engine
that runs the insert. If an engine has no registered dialect, a text value with
a backslash is rejected rather than rendered using an assumed escaping rule.

When this tool is called from a mission, its Prover progress is recorded with
the mission and is available live or through the mission replay. For the live
panel and phase proof cards in Document Flow, see [Prover progress in
missions](/docs/Missions/Missions-And-Tasks#prover-progress-in-missions).

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_profile_id` | string | — | Required execution profile id for the source estate. |
| `target_profile_id` | string | — | Required execution profile id for the migrated target estate. |
| `baseline_trace_hash` | string | `""` | Optional pinned source-oracle trace to reuse. A trace recorded with a different test-value rendering is refused; omit this parameter to record a fresh source trace. |

Before starting validation, the tool checks that the caller can see both execution
profiles and, when supplied, the baseline trace. For a caller-scoped request, every
connection named by a profile must be visible; a profile with no connection references is
visible only to someone who administers every connection. A hidden or missing profile
returns `unknown execution profile: <profile_id>`, and a hidden or missing trace returns
`unknown baseline trace: <trace_hash>`. Neither case starts a validation run.

When a Prover estate comparison uses this run to license a rewritten view, each profile must
identify the same database side as its comparison snapshot; matching connections alone is
not enough. See [Genesis Prover](/docs/Genesis-Prover/Overview) for the side-matching rules.

The response includes the validation result, `run_id`, stage, reproducibility,
validated-model and case counts, findings, and source/target trace hashes. When
`run_id` is present, it also includes `run_detail_url`, which opens the exact
run's verdict and per-case evidence in the validations view. This link is
provided for both clean and finding-bearing runs, including a failed run that
records the stage where it stopped.

Verdict rules and withheld-output semantics are covered in [Pipeline migration
proofs](/docs/Genesis-Prover/How-A-Run-Works#pipeline-migration-proofs).

For a prepared pipeline contract, the result includes the pipeline execution
evidence and `state_checks` described in [Pipeline migration
proofs](/docs/Genesis-Prover/How-A-Run-Works#pipeline-migration-proofs).

When the target executes a remote job, the response also includes
`execution_runs`: one entry for the bootstrap run and one for each plan step.
Each entry contains `step`, `databricks_run_id`, `job_id`, `result_state`, and a
`tasks` list. Each task contains `task_key`, `run_id`, and `result_state`, so a
finding can be traced to the Databricks job and task that produced its output.
Adapters that do not submit a remote job do not add `execution_runs`.

Databricks run evidence follows every Jobs API 2.2 `Get Run` page before building
the task list. If the response still carries `next_page_token` after pagination
cannot complete, validation returns `success: false` and does not write an
evidence report whose task count could understate the run.

If the validation fails after submitting a remote job, the response includes
`execution_run_ids` when available. It maps `source` and/or `target` to the
last Databricks run id submitted for that side, including when the active run
has already been released.

When `run_id` is present, the response also includes `human_review_url`, which
opens Human Review for this exact validation run with
`?view=review&validation=<run_id>`. It is present for both clean and
finding-bearing runs, so show both `run_detail_url` and `human_review_url` to
the user. Do not construct the address or substitute a diff-shaped link:
migration validation compares two transforms against the same designed
stimulus, rather than two characterized estates, and `?view=review&diff=<hash>`
opens the wrong comparison route.

Findings returned by a run that was recorded before durable finding keys were
introduced can still be read in the run detail and Human Review views, but
those findings do not include `finding_key` and cannot receive a recorded
diagnosis. Do not report a ruling as saved for such a finding.

### `get_migration_findings`

Fetch the finished summary and localized findings for one run returned by
`validate_migration`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `run_id` | string | — | Required id returned by `validate_migration`. |

For a migration-validation run, the response returns `success: true`, the
persisted summary in `run`, and the same `run_detail_url` and
`human_review_url` handoff fields described above. An unknown id or an id for
another run type returns `success: false` with an error and no link.

The returned terminal run record also exposes `outcome` beside `status`: read
`PASS`, `FAIL`, `INDETERMINATE`, `not_verified`, `no_findings`, or `sealed` rather
than inferring the decision from lifecycle status.

Behavioral validation findings expose structured row selectors and measured
source/target values; see the [estate findings API reference](/docs/Genesis-API/API-Reference#get-api-estate-findings)
for the evidence fields and missing-row semantics.

<a id="migration-intake-tools" />

## `migration_intake_tools`

Use this group to start a migration plan from chat. `ask_migration_connection`
presents the person's connections as a card when the source or destination is
still open; `find_migration_pipelines` reads lineage metadata for the source
database and presents a card of candidate pipelines; `propose_migration_plan`
binds the selected scope and presents an approval card;
`get_approved_migration_plan` reads the full approved boundary.
The intake and plan-reading calls do not run or modify a pipeline. After approval,
`start_migration` starts eligible plans as a Mission in the approving chat. These
tools require a signed-in person; plan approval is carried by the card's **Approve
and start** action, not by a typed confirmation. For the wizard flow and migration
stages, see [Database migration blueprints](/docs/Blueprint/Blueprint-Library-And-Missions#database-migration-blueprints).
`start_migration` launches in goal mode from Plan, and `start_onboarding` launches
in goal mode from its first phase. For mode behavior, see
[Blueprint Library and Missions](/docs/Blueprint/Blueprint-Library-And-Missions).

When a user chooses **Not sure? Continue with Eve** in the Launchpad migration
wizard, the handoff includes the choices already made and the remaining questions.
Keep those choices, resolve each `name (Platform)` to its registered connection
id, and continue with the first unanswered question; do not ask for a choice
again. If the handoff includes a `[BEGIN MIGRATION PIPELINE CHOICE]` block, use
its exact `pipeline_ids` in `propose_migration_plan` and do not present the
pipelines card again. Pipelines the user points out manually cannot be bound from
chat; explain that and offer the pipelines found through lineage instead. For
the user-facing wizard and card behavior, see [Migrate data and
pipelines](/docs/User-Guide/Chat-And-Threads#migrate-data-and-pipelines).

### `ask_migration_connection`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `side` | string | — | Required: `source` or `destination`. |
| `platform` | string or null | `null` | A connection type the person named, such as `postgres`; the card opens on that platform's connections. |
| `source_connection_id` | string or null | `null` | When asking for the destination, the chosen source's exact `connection_id` from the source answer's `connections`; the card leaves it out. |
| `card` | boolean | `true` | Set `false` when the person already named this side in a Launchpad guided pick. The response still includes `connections` for resolving the pick, but omits `presented` so Eve does not ask the same question again. |

The response always includes `connections` (`connection_id`, `name`, `type`).
With `card=true`, it also includes a `presented` card of those connections
grouped by platform, with search and a way to add a new connection; with
`card=false`, `presented` is omitted. A source request includes database connections the
person can see and pipeline-service connections the person and selected agent
may use; the source card offers up to 40 of those additional pipeline-service
connections. Foundry is already listed as a data source. Destinations remain
database connections, and the destination card offers a plan-only choice. A
destination response also includes `presented.new_container`: `terms` maps each
listed data-connection type to its container word (`catalog` for Databricks,
`dataset` for BigQuery, and `database` for other types), while `default_term` is
`database`. The destination card uses this offer to let the person name a new
container inside a listed connection. Ask for the source first; when asking for
the destination, pass the chosen source's `connection_id` as
`source_connection_id` so it is omitted from the choices. A connection click sends
one line naming the pick, such as "Migrate from etf\_vignette (PostgreSQL)." for the source or
"Migrate to lakehouse (Databricks)." for the destination; a new-container click
names the listed connection and the container to create, for example "Migrate to
lakehouse (Databricks), into a new catalog foundry\_migration." A typed answer
works too. A plan-only destination sends "Plan only, for Snowflake — there's no
connection yet." and continues with `target_platform: "snowflake"`. Each call
reads the registered connections; the source lookup also checks which additional
pipeline-service connections the person and agent may use. The response's `next.activate` names
`manage_context(action='ADD_CONTEXT', active_skills='plan-data-work')`; when the
skill is not active yet, make that activation in the same turn so the chat route
and its pipelines and plan cards are available.

When the destination is a new catalog or schema in a listed connection, pass
the chosen connection as `target_connection_id` and the requested catalog and
schema as `target_database` and `target_schema` to
`propose_migration_plan`. These fields select the namespace but do not create
it; create the catalog or schema before the data moves. For the user-facing
answer behavior, see
[Migrate data and pipelines](/docs/User-Guide/Chat-And-Threads#migrate-data-and-pipelines).

### `find_migration_pipelines`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_connection_id` | string | — | Required source connection as `type.name`. |
| `database` | string or null | `null` | Source database; when omitted, uses the database named by the connection. |
| `schemas` | string\[] or null | `null` | Optional schemas to include; omission covers the whole database. |

For a database source, the response includes grouped pipelines, their
read/write tables and code locations, `unproduced_tables`, `lineage_available`,
notes, and a `presented` pipelines card. Pass the kept `pipeline_id` values to
`propose_migration_plan`. If lineage is unavailable or finds no pipeline, a
data-only plan is still possible. The lookup reads the Context Graph and is
bounded to 45 seconds; an older graph can require table-by-table reads.

For a pipeline-service source, the tool does not query database lineage or
return a pipelines card. It checks that the person and agent may use the
connection and returns a `next.why` handoff instead. For Foundry, activate
`palantir_foundry_tools,palantir_foundry_migration_tools` and follow the Foundry
migration tools' `next_step` instructions; that workflow writes to Databricks.
For Airflow, Astronomer, or MWAA, activate `airflow_tools`; for dbt Cloud,
Matillion, Airbyte, or Fivetran, activate `dbt_cloud_tools`, `matillion_tools`,
`airbyte_tools`, or `fivetran_tools`, respectively. Inspect the pipelines, then
continue the migration intake with the database warehouse they load. If Genesis
has no tools for the selected pipeline service, ask which warehouse its
pipelines load and continue with that database connection.

### `propose_migration_plan`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_connection_id` | string | — | Required source connection as `type.name`. |
| `target_connection_id` | string or null | `null` | Destination connection. Omit only for a plan-only request with `target_platform`. |
| `selected_pipeline_ids` | string\[] or null | `null` | Kept pipeline ids from `find_migration_pipelines`; empty means data only. |
| `database` | string or null | `null` | Source database; omission uses the connection's database. |
| `schemas` | string\[] or null | `null` | Optional source schemas; on a data-only plan, omission includes every schema. |
| `target_platform` | string or null | `null` | Plan-only destination platform: `snowflake`, `databricks`, or `other`. Required when no target connection is supplied. |
| `target_runtime` | string or null | `null` | Rebuild runtime: `dbt`, `declarative_pipeline`, or `databricks_job`. When pipelines are selected, defaults to `dbt` for Snowflake and `declarative_pipeline` for Databricks; runtime choices are target-specific. |
| `target_database` | string or null | `null` | Destination database or catalog, when specified. |
| `target_schema` | string or null | `null` | Destination schema, when specified. |

The plan response includes the selected objects and their roles, destination,
pipeline list, candidate row keys and their basis, Prover checks, applied
defaults, notes, and the checksummed bound scope. Proposing performs bounded
Context Graph and source-catalog reads and writes the scope record. Only the
approval action on the presented plan card approves it. Use
`get_approved_migration_plan` with the approved `server_scope_id` to read the
complete bound object and pipeline lists.

### `get_approved_migration_plan`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `server_scope_id` | string | — | Required id from the approved plan card or migration intake block. |

Returns the checksummed source and target boundary, selected objects and
pipelines, pinned code revisions, target namespace, naming and runtime. Only the
person who approved the plan can read it, while they retain access to its
connections.

### `start_migration`

Call with no arguments on the turn carrying the plan card's **Approve and
start** action or a Launchpad hand-off. A typed “yes” is not approval and starts
nothing. The response includes the Plan phase instructions; follow them. See
[Approved chat migration blueprint](/docs/Blueprint/Blueprint-Library-And-Missions#approved-chat-migration-blueprint)
for the phases and supported-plan rules.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `bot_id` | string or null | `null` | Injected agent id; do not pass as a tool argument. |
| `thread_id` | string or null | `null` | Injected current chat id; do not pass as a tool argument. |
| `user_id` | string or null | `null` | Injected signed-in person id; do not pass as a tool argument. |
| `input_metadata` | dictionary or null | `null` | Injected approval-turn metadata; do not pass as a tool argument. |

The tool reads the approved scope record, checks visibility for each bound
connection, and checks the `ratify_source_contract` permission. On success, it
creates the Mission project, Git repository, and thread properties, then enters
the Plan phase. A typed approval or a second plan cannot restart an existing
migration; start a new chat to run another plan.

Example: on the approval turn, call `start_migration()` with no arguments. The
response includes the Mission details, Plan phase instructions, and the approved
plan's `server_scope_id`.

<a id="onboarding-intake-tools" />

## `onboarding_intake_tools`

Use this group when Eve is onboarding raw or bronze tables into an existing
silver table with the `bronze_to_silver_onboarding` blueprint. The tools present
the connection, raw tables, target table, and approval plan as chat cards; they
do not map or load data themselves. All database lookups run as the signed-in
person and read their visible connections or live catalog. For the chat flow,
see [Onboard raw tables](/docs/User-Guide/Chat-And-Threads#onboard-raw-tables).

### `ask_onboarding_connection`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `platform` | string or null | `null` | Optional platform the person named, such as `databricks`; the card opens on that platform when a matching visible connection exists. |

The response includes every database connection visible to the person and a
card grouped by platform, with search and a way to add a connection. Each call
reads the registered database connections. Once the connection is known, use
`find_onboarding_tables`.

### `find_onboarding_tables`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `side` | string | — | Required: `source` lists raw or bronze tables; `target` lists silver tables to map into. |
| `connection_id` | string | — | Required visible database connection as `type.name`, such as `databricks.lakehouse`. The source and target use the same connection. |
| `database` | string or null | `null` | Optional database (catalog on Databricks); provide it when the person names one. Otherwise Genesis chooses the database for the requested layer or the connection's default. |
| `schema` | string or null | `null` | Optional schema to list when the person names one. |

The call reads the live catalog: it may read the database list, reads schemas,
and reads each listed schema (up to four). The response includes table names as
`catalog.schema.table` (up to 200), schemas, connection details, and a card with
checkboxes for source tables or a single target-table choice. After both picks,
call `propose_onboarding`.

### `propose_onboarding`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_connection_id` | string | — | Required visible source connection as `type.name`. |
| `source_tables` | string\[] | — | Required raw tables, each named `catalog.schema.table`. |
| `target_table` | string | — | Required existing silver table, named `catalog.schema.table`, on the same connection as the sources. |
| `documents_folder` | string or null | `null` | Optional folder containing the mapping guide and data dictionary. If omitted, the plan card asks for a Git folder or files to upload before approval. |
| `source_name` | string or null | `null` | Optional source label; when omitted, uses the last component of the first source table name. |

This call validates the picks against the live catalog, querying each named
schema. Its response includes the plan and a card with the workflow steps and
approval controls. Only **Approve and start** approves; typed confirmation does
not. The card's load option is enabled by default. Use this tool again when the
person changes picks or supplies the documents folder.

Example:

```python theme={null}
propose_onboarding(
    source_connection_id="databricks.lakehouse",
    source_tables=["main.bronze.orders_raw"],
    target_table="main.silver.orders",
    documents_folder="onboarding-docs/orders",
)
```

### `start_onboarding`

Call with no arguments on the turn the person presses **Approve and start** on
the plan card. It reads the approved picks from that turn, confirms the person
still has access to the source connection, and starts the blueprint as a
Mission in the current thread. A typed “yes” or “go” does not start it. If the
thread already has an onboarding Mission, another approval does not replace its
original picks.

<a id="migration-prover-tools" />

## `migration_prover_tools`

Use `migration_prover_tools` when a migration validator needs to design, prepare,
run, and inspect a behavioral data-migration proof with approved stimulus cases,
including the behavior proof of a rewritten view. For proving a migration by
comparing two estates and grading a spec, use `prover_tools` instead. This group
contains `design_stimulus_campaign`, `prepare_migration_prover`,
`preflight_databricks_job_contract`, `validate_migration`, and
`get_migration_findings`; it is **not** always-on. See
the detailed tool definitions above for the required credential-free profiles,
approval flow, and validation findings. Its answers carry the same agent-audience
marker described under [`prover_tools`](#prover-tools).

<a id="measurement-tools" />

## `measurement_tools`

Freeze portable records of database estates, read them back, declare how two
frozen estates relate, and compare them — without opening live database
connections for the compare step. This group is **not** always-on; agents
receive it when a migration or measurement workflow needs it.

**Permission gate:** every tool in this group requires `manage_all_connections`,
including reads. Frozen records and qualification reports can disclose per-column
value evidence from customer estates. The in-app measurement tabs under
**Migration verification** use the same gate via
`/api/transition_contract/measure/*`.

**Relationship to `transition_contract_tools`:** transition-contract tools
compile and execute governed verification runs against live estates with a rule
registry and human ratification. Measurement tools work on **frozen** records
already stored in the registry. For ad-hoc keyed spot checks without the
transition-contract registry, use `verify_against_contract` from
`system_diff_tools` instead.

`characterize_and_freeze_estate` also closes a run when its background hand-off is
refused. The response carries `success: false`, the `run_id`, and `status: "error"`;
if terminalization fails, it adds `terminalization_failed: true` and reports that the
row may remain `running` until startup reconciliation.

| Tool | Purpose |
| - | - |
| `characterize_and_freeze_estate` | Measure schemas on a connection and freeze a portable record (background run; poll with `get_measurement_run`). |
| `get_measurement_run` | Poll one measurement run by `run_id` until `finished_at` is set. |
| `render_frozen_contract` | Read one frozen record back (`frozen_contract_hash`). |
| `declare_measure_correspondence` | Declare how two frozen estates relate before comparing them. |
| `diff_frozen_contracts` | Compare two frozen records under a `correspondence_hash` from `declare_measure_correspondence`. |

### `characterize_and_freeze_estate`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `connection_id` | string | none | Named database connection holding the estate to measure. |
| `database` | string | none | Database (or catalog) name within that connection. |
| `schemas` | string | none | JSON array of schema names to measure, or comma-separated names. |
| `attested_by` | string | `""` | Who asserts the estate was quiet during measurement. Required for non-PostgreSQL engines. |
| `attestation_window` | string | `""` | Window the attestation covers (for example a cutover freeze period). Required alongside `attested_by` when attestation applies. |
| `budget_seconds` | integer | none | Optional wall-clock ceiling for this run in seconds. Must be positive; larger requests are reduced to the deployment ceiling. |

Returns immediately with `run_id` and `status` `running`. Poll `get_measurement_run` until terminal. A succeeded run includes `frozen_contract_hash` for `render_frozen_contract` and `diff_frozen_contracts`. The frozen record's `created_by` is the signed-in user, or `unattributed` when the turn has no signed-in user; `attested_by` remains the separate claim about who asserted quiescence. Read the author from `render_frozen_contract` rather than treating `attested_by` as the record author.

### `declare_measure_correspondence`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_contract_hash` | string | none | Frozen record of the source estate. |
| `target_contract_hash` | string | none | Frozen record of the target estate. |
| `relation` | string | none | `same_estate`, `loaded_from_at_or_after`, or `declared_equivalent`. |
| `evidence_kind` | string | none | `migration_run`, `load_log`, `change_feed`, `audit_record`, `ticket`, or `operator_attestation`. |
| `evidence_reference` | string | none | Something a reader could follow. |
| `grade` | string | `unverified` | `unverified` licenses nothing; `decided`, `exhaustive`, or `statistical` when evidence backs the claim. |
| `regions` | string | `""` | JSON array of schema names. Empty licenses the whole estate and requires `acknowledges_estate_wide`. |
| `object_renames` | string | `""` | JSON object mapping source object name to target object name. |
| `acknowledges_estate_wide` | boolean | `false` | Required when `regions` is empty. |

The caller does not provide `declared_by`. Genesis records the declaration on
the signed-in user's identity and, on a bot turn, includes the acting agent in
that recorded principal. A scheduled or bot-only turn without a signed-in user
is refused with `refusal_code: "NO_HUMAN_PRINCIPAL"` and stores nothing.
Successful responses include `correspondence_hash`, `declared_by`, and
`declared`.

### `diff_frozen_contracts`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `source_contract_hash` | string | none | Source frozen record. |
| `target_contract_hash` | string | none | Target frozen record. |
| `correspondence_hash` | string | none | Declaration from `declare_measure_correspondence`. |

Read `object_pairing` before the counts in the response. An `unverified` declaration licenses no comparison — covered regions come back indeterminate.

See [Data Explorer — Measurement tabs](/docs/User-Guide/Data-Explorer#prepare-and-check-measurement-tabs) and [measurement endpoints](/docs/Genesis-API/API-Reference#measurement-endpoints) for the operator UI and REST equivalents.

<a id="user-memory-action-tools" />

## `user_memory_action_tools`

Manage durable per-agent user memory and one-on-one checklist progress during
onboarding and weekly check-ins. Genesis auto-admits this tool group (via the
`access-onboarding` and `one-on-one-checkins` guidance skills) whenever an
onboarding or one-on-one session is active, so the lead agent can persist
checklist updates with `SET_ONE_ON_ONE_CHECKLIST` instead of stalling on
invented topic keys.

### `user_memory_action`

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | none | Required. One of `ADD_NOTE`, `COMPLETE_ONE_ON_ONE`, `EDIT_NOTE`, `GET_FULL`, `GET_ONE_ON_ONE_STATUS`, `GET_SUMMARY`, `REMOVE_NOTE`, `SET_ONE_ON_ONE_CHECKLIST`, `SKIP_OPTIONAL`, `START_ONE_ON_ONE`, or `UPSERT_CATEGORY`. |
| `category_key` | string | `null` | For `UPSERT_CATEGORY`: `preferred_name`, `job_role`, `technical_level`, `language`, `main_data_sources`, `connectors_of_interest`, `connection_identifiers`, `preferences`, or `objectives`. |
| `category_value` | object | `null` | Category value for `UPSERT_CATEGORY`. String or list depending on the category. |
| `append` | boolean | `false` | When `true` for list categories, append values instead of replacing. |
| `note_id` | string | `null` | Note id for `EDIT_NOTE` or `REMOVE_NOTE`. |
| `note_text` | string | `null` | Note text for `ADD_NOTE` or `EDIT_NOTE`. |
| `note_category` | string | `null` | Optional note category for `ADD_NOTE` or `EDIT_NOTE`. |
| `topic_key` | string | `null` | Exact checklist topic key for `SET_ONE_ON_ONE_CHECKLIST`. Must match a current checklist key verbatim. Default required keys are typically `name_and_language`, `job_role`, `data_sources`, and `validated_data_access`; default optional keys are typically `collaboration_preferences`, `short_term_objectives`, and `broader_goals`. Do not invent keys (for example `onboarding`). If unsure, call `GET_ONE_ON_ONE_STATUS` first to read the exact `topic_key` values configured for the workspace. |
| `section` | string | `null` | Checklist section for `SET_ONE_ON_ONE_CHECKLIST`: `required` or `optional`. Defaults to `required` when omitted. |
| `completed` | boolean | `null` | Required for `SET_ONE_ON_ONE_CHECKLIST`. |
| `details` | string | `null` | Optional short details or feedback summary for checklist updates. |
| `unlock_user` | boolean | `false` | For `COMPLETE_ONE_ON_ONE`: when `true`, unlock onboarding for this user. |
| `unlock_result` | string | `null` | Optional unlock result reason for `COMPLETE_ONE_ON_ONE`. |
| `valued_access_available` | `string[]` | `null` | Optional list of validated valued access items for unlock summary. |
| `valued_access_missing` | `string[]` | `null` | Optional list of missing valued access items for unlock summary. |
| `next_actions_for_admin` | `string[]` | `null` | Optional list of admin next actions for unlock summary. |
| `summary_preview` | string | `null` | Optional onboarding summary preview for unlock. |
| `feedback_summary` | string | `null` | Optional feedback summary to persist at one-on-one completion. |
| `user_id` | string | implicit | Derived from the requesting user context. |
| `bot_id` | string | implicit | Derived from the acting agent context. |
| `thread_id` | string | implicit | Derived from the active thread. |

`SET_ONE_ON_ONE_CHECKLIST` rejects unknown `topic_key` values. The error lists
the valid required or optional keys for the workspace so the agent can retry
with an exact match. Legacy aliases such as `preferred_name` and
`language_preference` are normalized to `name_and_language` in the required
section only.

Example:

```text theme={null}
user_memory_action(action="GET_ONE_ON_ONE_STATUS")

user_memory_action(
  action="SET_ONE_ON_ONE_CHECKLIST",
  topic_key="job_role",
  section="required",
  completed=true,
  details="Director of Data Engineering"
)
```

<a id="snowflake-ai-tools" />

## `snowflake_ai_tools`

Access Snowflake Cortex AI capabilities from Genesis. In practice, this maps
most directly to [Cortex Agent Tools](/docs/Genbot-Toolkit/Cortex-Agent-Tools),
[Cortex Search Tools](/docs/Genbot-Toolkit/Cortex-Search-Tools), and Cortex
Code workflows.

<Note>
  When an administrator has hidden the virtual System `Snowflake` connection,
  agent-facing Snowflake SQL helpers (`_run_query_sqlapi`, `_run_query_async`),
  Cortex tools (`_cortex_search`, `_cortex_agent`), and Snowpark entry points
  that default to `connection_id="Snowflake"` return `success: false` with
  `type: connection_disabled` if the call targets that connection. Use a
  user-created saved Snowflake connection id instead. Internal non-agent callers
  are unaffected.
</Note>

### `_cortex_code`

Delegate repo-scoped coding and Snowflake-connected tasks to Cortex Code
(`Coco`) from inside a Genesis thread. The preferred flow is async:
`action="submit"` to start work, then `check_status`, `get_results`, or
`send_message` using the returned `session_handle`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `action` | string | `submit` | One of `submit`, `check_status`, `get_results`, `cancel`, `send_message`, `run`, or `get_capabilities`. |
| `task` | string | `null` | Required for `submit`, `run`, and `send_message`. Coding task or follow-up instruction. |
| `session_handle` | string | `null` | Required for `check_status`, `get_results`, `cancel`, and `send_message`. |
| `session_handles` | `string[]` | `null` | Optional multi-session form for `check_status`. Returns when any listed session has a meaningful update. |
| `repo_id` | string | thread-scoped uploads workspace | Optional bot-git repo id for Cortex Code's working directory. |
| `repo_path` | string | repo root | Optional subdirectory within `repo_id`. It must resolve inside that repository; `..` escapes are rejected. |
| `timeout_seconds` | integer | `300` | Sync `run` timeout. Ignored for async `submit`. |
| `include_thinking` | boolean | `false` | Include reasoning output when available. |
| `snowflake_connection` | string | auto-select | Optional saved Snowflake connection id. In Snowflake Native App / SPCS deployments, use a user-created saved connection rather than the built-in system `Snowflake` connection. |
| `save_session_log` | boolean | `true` | Save a markdown session log when the run finishes and return its path when available. |
| `wait_for_update_seconds` | integer | `30` | `check_status` long-poll window. Set `0` for an immediate status check. |
| `settle_seconds` | integer | `2` | Extra wait after new output arrives during `check_status`. |
| `status_summary` | string | `null` | Optional user-facing progress text for single-session `check_status`. |
| `status_summaries` | object | `null` | Optional per-session progress text for multi-session `check_status`. |
| `diagnostic` | boolean | `false` | Include raw CLI diagnostic paths and sync CLI output when available. |
| `injected_credentials` | array | `null` | Optional credential connections to inject. Items can be strings or objects. |
| `credential_policy` | string | `none` | One of `none`, `explicit_only`, or `least_privilege`. |
| `credential_ttl_seconds` | integer | `900` | TTL for injected credentials during session reuse. |

<Note>
  When the task text or failure output mentions `boto3`, AWS SDK work,
  EKS/Kubernetes, Helm, `kubectl`, AWS CLI, cloud deployment, or cloud
  monitoring, `_cortex_code` can return `agent_reminders`,
  `sandbox_tools_recommended`, and `sandbox_tools_reference` instead of
  retrying blindly in the Genesis application container. Use `sandbox_action`
  with `backend="eks"` or `backend="k8s"` and the
  `aws-eks-sandbox-operations` skill for those workflows.
</Note>

Example:

```text theme={null}
_cortex_code(
  task="Review the dbt models in this repo and suggest a safe fix plan.",
  repo_id="analytics"
)

_cortex_code(
  action="check_status",
  session_handle="cc_abc123",
  status_summary="Reviewing the repo and summarizing the safest fix path."
)
```

<Note>
  `_cortex_code` now applies prompt and response safety guards. Risky prompt
  text or returned content that appears to expose host data or secrets can be
  blocked with `success: false`, `error: "Request blocked by safety policy."`,
  and `coding_agent_safety_rejected: true`. The same safety layer sanitizes
  streamed session events before they are broadcast, and Cortex Code strips
  ambient secret env vars such as `AWS_ACCESS_KEY_ID`,
  `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` from the sandboxed process
  environment.
</Note>

### `_run_query_sqlapi` and `_run_query_async`

These Snowflake SQL helpers execute SQL through the Snowflake SQL API.
`_run_query_sqlapi` runs the statement immediately, while `_run_query_async`
uses `action="submit"` and later polling with `check_status` or `get_results`.

| Parameter | Applies to | Type | Default | Description |
| - | - | - | - | - |
| `confirm` | both tools | boolean | `false` | Re-call a previously blocked destructive statement such as `DROP TABLE`, `DELETE`, `TRUNCATE`, or `CREATE OR REPLACE TABLE` after review. |
| `user_override` | both tools | string | `""` | Re-call a blocked catastrophic namespace operation such as `DROP DATABASE`, `DROP SCHEMA`, `DROP CATALOG`, or `CREATE OR REPLACE DATABASE/SCHEMA/CATALOG` after explicit user approval. The value must exactly match the returned `statement_type`, such as `DROP DATABASE`. |

<Note>
  If either tool returns `requires_confirmation: true`, review the returned
  `classification` and `sql` before retrying. `confirm` does not authorize
  `CATASTROPHIC` operations, and multi-statement catastrophic work must be
  split into single-statement calls so `user_override` applies to exactly one
  operation.

  When the optional SQL intent-match guard is enabled, these Snowflake SQL
  helpers can also return `requires_confirmation: true` with
  `severity: intent_mismatch` when the planned SQL does not clearly match the
  user's latest request. In that case, wait for a fresh chat reply that
  explicitly names the exact operation and target before retrying. `confirm`
  or `user_override` can still be required afterward by the normal SQL safety
  gate.
</Note>

Example:

```text theme={null}
_run_query_async(
  action="submit",
  query="DROP DATABASE scratch_db",
  user_override="DROP DATABASE"
)
```

<a id="genesis-auditor-tools" />

## `org_health_tools`

The `org_health_tools` group is the private, read-side loadout for the
customer-facing **GenesisAuditor** agent. It audits the deployment's AgentSkills
packages, blueprints, and live agent activations against the pinned Genesis
Organization Model, then reports structural findings with source coordinates.
Only the `GenesisAuditor` identity can invoke this group; it is not discoverable
by other agents. Its separate `org_health_fix_tools` group proposes the auditor's
fixes for a person to apply in Action Review; this read group has no configuration,
data-connector, or handoff tool.

The audit reads the deployment's files and metadata. Run it once for a review and
use the returned `summary` for complete counts and rankings. By default, the audit
returns findings from `organization` content: content the customer authored or
imported. Use `platform` for Genesis-shipped content, or `all` for both content
universes plus findings whose provenance is unknown. Findings against a live agent's
own configuration (`agent:<agent_id>`) are always organization findings because the
deployed configuration is administered by this organization, regardless of who
seeded the agent. The summary always reports all, organization, platform, unknown,
and hidden totals for findings and unclassified references, so you never claim more
than the requested scope shows. Do not present findings or unclassified references
from another scope unless the user asks about that content. The findings,
unclassified references, and co-load index can be paged when the response exceeds the
inline tool-output budget.
Every page re-runs the audit and uses `audit_id` plus the same scope to refuse a
continuation when the organization or visible audit lists changed between calls.

Skill activation findings use the runtime's identity resolution order rather than
matching pins to package directories by name alone. A package's `SKILL.md`
frontmatter `name` and supported compatibility aliases can resolve to that package;
when a package directory has the same name as a requested identity, the directory
identity takes precedence. Repository-backed skill specs are also checked by reading
their names from the existing `skills/skills_repository.json` file without creating
or seeding a repository. This prevents a valid frontmatter name, compatibility
alias, or repository-backed spec from being reported as a missing skill. If the
repository file exists but cannot be read or parsed, the audit reports a read gap
instead of claiming that no spec resolves the pin.

When the audit reads a Git-backed skill's full document, it uses the package
already admitted for that read. With `features.skill_revision_tracking` off (the
default), it reads from that package's checkout; when revision tracking governs
the skill, it reads from the pinned revision.

### `run_organization_audit`

Run the organization audit for a requested content scope. No business data is queried
or changed, and this read-side operation does not modify audited artifacts.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `scope` | string | `organization` | Findings to return: `organization` for customer-authored or imported content, `platform` for Genesis-shipped content, or `all` for both plus unknown provenance. Hidden counts are always returned. |
| `bot_id` | string | implicit | Acting agent identity; must resolve to `GenesisAuditor`. |

The response includes the pinned doctrine name and hash, deployment and corpus
metadata, findings with `provenance`, `unclassified_references` with each reference's
file and line coordinates plus provenance, counts, `summary`, co-load totals, and
`read_gaps` when part of the deployment could not be read. Unclassified references
could not meet the analyzer's evidence gate, so inspect them under the audit response's
"could not classify — check these" heading rather than treating them as dead references
or defects. A finding that spans owners can appear in both `organization` and
`platform` scopes because each owner has a copy to act on. Use
`get_organization_finding` for the source behind a finding,
`get_organization_co_load_set` for one co-load breakdown, and
`get_organization_skill` for a complete skill document.

### `get_organization_audit_page`

Continue one list from a response whose corresponding page reports
`complete: false`. This tool is also read-only, but it re-runs the full audit on
each call. Pass the same `scope` as the page being continued; the audit reference
and scope together identify the visible findings list.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `section` | string | none | Required. `findings`, `unclassified_references`, or `co_load_index`. |
| `offset` | integer | none | Required. The section's `next_offset`. Must not be negative. |
| `audit_id` | string | none | Required. The `audit_id` from the response being continued. |
| `scope` | string | `organization` | The finding scope from the page being continued: `organization`, `platform`, or `all`. |
| `bot_id` | string | implicit | Acting agent identity; must resolve to `GenesisAuditor`. |

If the inline budget cannot fit even one entry at the requested offset, the tool
returns an error rather than a cursor that cannot advance. The budget is controlled
by `tools.output_governor.inline_budget_bytes`.

## `org_health_fix_tools`

The `org_health_fix_tools` group holds **GenesisAuditor**'s fix proposals. Only the
`GenesisAuditor` identity can invoke it, and it never changes anything itself: each
tool files an `org_health.fix.v1` proposal in Action Review, which always waits for a
person, even when admission policy would allow the action. The fix is applied only when
a person who may manage the target approves and applies it. The group is silent by
default (`org_health.fix_mode`), and only organization-owned content can be fixed. The
user must explicitly ask GenesisAuditor for a fix; an earlier audit finding is not
authority to propose one.

When a person applies a fix, Genesis re-checks the fix mode, the person's right to
manage the target, and the target itself. It writes only if the target still holds
exactly the state the approved proposal expected. The execution receipt records the
state the fix replaced, so the fix can be reversed.

For fixes that edit a whole blueprint manifest or skill document, Genesis measures
the handler-known serialized proposal content before admission. If it exceeds the
`org_health.proposal_payload_max_bytes` ceiling, the fix is refused before an Action
Review proposal is stored. See [Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix)
for the `750000`-byte default and fallback behavior.

### `remove_dead_skill_pin`

Propose removing one skill pin from a target bot's `active_skills` context default.
The proposal re-checks the current policy, skill corpus, aliases, specs, and the
agent's live pin list, and keeps every other stored pin unchanged. Nothing changes
until a person applies it; applying repeats the proof and refuses if the agent's pins
or skill access policy changed since the proposal. The response reports
`pending_review` and the `action_review.proposal_id`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `bot_id_target` | string | required | Bot whose `active_skills` default contains the inert pin. |
| `pin_name` | string | required | Exact skill pin to re-check and propose removing if it is still inert. |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the target. |

Proposing refuses when the identity is missing or incorrect, the fix mode is not
`active`, the requesting user may not manage the agent, the target cannot be
canonicalized, the doctrine or gate cannot be read, or the pin is not inert. See
[Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix) for the
configuration key and default.

### `admit_blocked_skill`

Propose admitting one skill that an agent activates but its own skill access policy
excludes. Use this for an `OH-AGENT-SAT` finding after asking the user which of the
two honest resolutions they want: admit the skill with this tool, or remove the
activation with `remove_dead_skill_pin`. This tool changes only that skill's
treatment in the access list; it never changes `skill_access_mode` or widens the
agent to all skills. Nothing changes until a person who may manage the agent applies
the proposal in Action Review. The response reports `pending_review` and the
`action_review.proposal_id` while it is waiting.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `bot_id_target` | string | required | Agent whose own access policy excludes a skill it activates. |
| `skill_name` | string | required | Exact name of the activated skill the agent's access policy blocks. |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the target. |

The proposal re-proves that the agent still activates the skill, that its policy
still excludes it, and that the skill would load after admission. It refuses for a
system seat such as `GenesisAuditor` or Eve, an already-permitted skill, a skill the
agent no longer activates, or a name that resolves to no skill package. It also
refuses a repository-backed skill spec because that spec loads without a
`SKILL.md` body; author a skill package for the name or retire the spec instead.
For an allowlist, the proposal adds the skill name; for a denylist, it removes the
name. See [Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix)
for the configuration key and default.

### `repair_blueprint_skill_requests`

Propose repairing every selected phase in one organization blueprint that requests
a skill which does not exist. Pass one entry in `repairs` for each missing skill:
omit `replacement` to remove the missing name, or provide an existing skill only
when the user explicitly chose that replacement. Omit `phases` to repair every
phase that requests the missing skill. The proposal re-checks the missing names,
replacement packages, blueprint source, and manifest before filing the edited
manifest for Action Review. Nothing changes until a person with permission to
manage the blueprint applies it.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `blueprint_name` | string | required | Organization blueprint whose phases request missing skills. |
| `repairs` | array of objects | required | Entries with `skill` (string), optional `replacement` (string), and optional `phases` (array of phase IDs). |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the blueprint. |

The tool refuses a replacement that is not an existing skill package, a blueprint
whose source is remote or cannot be established as local, or a second proposal for
the same blueprint after the first has been applied. Applying the proposal rewrites
the manifest, so YAML comments in that manifest are not preserved; the prior text
is recorded so the fix can be reversed. Whether a replacement is admitted by the
agent's skill policy is not checked. See [Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix)
for the configuration key and default.

### `repair_dead_skill_reference`

Propose repairing every selected dead skill reference in one organization's `SKILL.md`.
Pass one entry in `repairs` for each dead reference in that document: omit `replacement`
to remove the reference wherever it occurs, or provide an existing skill only when the
user explicitly chose that replacement. Put every dead reference in the document in one
call; the proposal is compared against the whole document, so a second proposal is
refused after the first is applied. Nothing changes until a person with permission to
manage skills applies the proposal in Action Review.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `skill_name` | string | required | Organization skill whose `SKILL.md` contains the dead references. |
| `repairs` | array of objects | required | Entries with `reference` (string) and optional `replacement` (string). Include every dead reference in this document in one call. |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the skill. |

The tool re-checks each dead reference at its exact lines, verifies each replacement is
an existing skill, and proves the edited document still loads without the finding or new
findings. Removal is supported only when the reference occupies a whole list item, table
row, or line; a reference inside a sentence is refused and must be repointed or rewritten
by a person. References that could not be classified, skills published by managed
repositories, and skills Genesis ships are refused. See [Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix)
for the configuration key and default.

### `cut_routing_cycle`

Propose cutting one user-selected edge from an `OH-CYCLE` routing cycle. Pass the skill
whose routing row should be deleted and the skill that row points to; this tool never
chooses the edge for the user. One call proposes one edge, and nothing changes until a
person who may manage the skill applies the proposal in Action Review. The proposal
re-checks that the skills are still in a routing cycle and that deleting the selected row
breaks their remaining paths. If another path still connects them, the proposal is
refused and names the skills that continue to cycle so the user can choose another edge.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `skill_name` | string | required | Organization skill whose routing row carries the edge to cut. |
| `routes_to` | string | required | Skill that `skill_name`'s routing row points to; the user-selected edge is `skill_name` → `routes_to`. |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the skill. |

The proposal deletes only a whole routing row whose only backticked content is the
routed cell. Rows containing another skill, another backticked token, or the routed
skill repeated in prose are refused and left for a person; rows in the frontmatter block
are never deleted. Skills published by managed repositories and platform skills Genesis
ships are also refused. Any other cycles remain listed on the Action Review card, and the
user is told about them before approval. The response reports `pending_review` and
`action_review.proposal_id` while the proposal waits. See [Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix)
for the configuration key and default.

### `retire_broken_blueprint`

Propose hiding one organization blueprint whose manifest has an `OH-PARSE` finding.
The proposal re-checks that the manifest still fails to parse and files removal of
the blueprint's registration from the live listing. The manifest is not deleted,
and a person can reverse the applied fix through `reverse_org_health_fix`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `blueprint_name` | string | required | Organization blueprint whose manifest the audit reports as `OH-PARSE`. |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the blueprint. |

Retiring a managed-source blueprint also requires repository-management permission
from the person applying it. A blueprint synced from a remote repository is not
edited by this tool; change it in the source repository instead. See [Advanced Settings](/docs/Setup/Advanced-Settings#organization-health-fix)
for the configuration key and default.

### `reverse_org_health_fix`

Propose undoing one applied organization fix by restoring exactly the state the fix
recorded before it changed anything. Like a fix, the reversal waits in Action Review
for a person who may manage the target. A reversal proves only that nothing about the
target's recorded state changed since the fix: for a dead skill pin, the agent's pins
and its skill access policy; for a blueprint skill repair, the manifest text; and for
a retired blueprint, its registration. It does not repeat the fix's own check. It is
refused if the fix was never applied, if it is itself a reversal, or if any recorded
field changed after the fix, when proposed and again when applied.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `fix_proposal_id` | string | required | The Action Review proposal ID of the applied fix to undo. |
| `bot_id` | string | implicit | Calling identity; must resolve to `GenesisAuditor`. |
| `thread_id` | string | implicit | Current thread; the Action Review card is sent there. |
| `user_id` | string | implicit | The requesting user; must be allowed to manage the target. |

### `get_organization_finding`

Read the evidence at a finding's exact coordinate before describing it to a user.
For a corpus file, the response returns surrounding source lines. For a live-agent
coordinate such as `agent:<agent_id>`, it returns the agent's activation evidence.
The default scope is `organization`; pass `platform` or `all` only when the user asks
about that content. The response includes provenance counts for that coordinate.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `file` | string | none | Required. Corpus-relative path or `agent:<agent_id>` from the finding. |
| `line` | integer | none | Required. 1-based line number for a file finding; use the finding coordinate for agent findings. |
| `context_lines` | integer | `12` | Lines returned on each side of a file coordinate. |
| `scope` | string | `organization` | Findings to return at this coordinate: `organization`, `platform`, or `all`. Hidden local counts are always returned. |
| `bot_id` | string | implicit | Acting agent identity; must resolve to `GenesisAuditor`. |

### `get_organization_co_load_set`

Open one co-load set to see each member's character contribution, provenance, missing
members, blocked members, source coordinate, and total size.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `kind` | string | none | Required. `agent`, `blueprint_phase`, or `role`. |
| `key` | string | none | Required. The key from `co_load_index`: an agent ID, role name, or `<blueprint>/<phase>`. |
| `bot_id` | string | implicit | Acting agent identity; must resolve to `GenesisAuditor`. |

### `get_organization_skill`

Read one complete `SKILL.md`, including frontmatter. The response includes the
document text, character count, path, and whether the result is complete.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `skill_name` | string | none | Required. AgentSkills package name from the audit inventory. |
| `bot_id` | string | implicit | Acting agent identity; must resolve to `GenesisAuditor`. |

### `audit_organization_health`

This entry point is in `system_manager_tools`, which Eve holds. It starts a hidden,
background GenesisAuditor thread and returns its `thread_id` and `handoff_id`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `focus` | string | `null` | Optional description of the user's concern, such as an agent, skill, or suspected duplication. |
| `bot_id` | string | implicit | Calling agent identity; used to authorize the spawn. |
| `thread_id` | string | implicit | Current thread context. |
| `user_id` | string | implicit | Requesting user context. |

The background run reads the organization's skills, blueprints, and agent records;
it can spend model budget and creates a thread and messages, but the auditor's own
loadout cannot modify the audited organization.
