Skip to content

Result and recovery contracts

Frigg keeps result size, coverage, trust, identity, and recovery separate. Consume these fields directly instead of inferring truth from row counts or prose notes.

response_mode controls structured payload detail:

Mode Contract
compact Default. Omits bulky metadata and note fields while keeping rows, completeness, handles, targets, trust, recovery, and next_actions.
full Adds ranking, selection, runtime, and diagnostic detail.

It is accepted by search_text, search_hybrid, search_symbol, search_batch, the six navigation tools, document_symbols, and impact_bundle. It is not accepted by workspace/file tools, inspect_syntax_tree, or search_structural.

presentation_mode controls bounded read output:

Mode Contract
text Default source bytes as MCP text content; no structured content.
json Structured path, line, byte, content, and optional efficiency fields.
citation MCP text with 1-based `LINE

read_file, read_match, and explore(operation=zoom) support all three modes. explore probe/refine remain structured and reject text presentation. include_context_efficiency=true requires JSON on read surfaces.

Every bounded collection carries an explicit completeness envelope:

Field Meaning
unit Row unit: occurrence, file, symbol, reference, definition, declaration, implementation, incoming/outgoing call, document symbol, syntax node, structural match, batch probe, or impact section.
returned Rows in this page, not a cumulative count.
total Exact cardinality only when Frigg can prove it. Missing means unknown, never a lower bound.
complete Frigg proved the normalized request is exhausted.
truncated A deliberate bound omitted otherwise eligible rows.
truncation_reasons page_limit, per_file_limit, top_k_limit, child_limit, merge_page_limit, or ancestor_limit.
incomplete_reasons Why coverage cannot be exhaustive.
continuation Opaque next-page token when deterministic paging is possible.

Incomplete reasons include ranked_discovery, diagnostic_coverage, unreadable/walk/backend failures, unsupported backend semantics, partial/heuristic/unavailable navigation coverage, and child_incomplete.

Read all of unit, complete, truncated, and the reason arrays. For example, a page can be intentionally truncated and still have an exact total, while a ranked discovery result can be untruncated but non-exhaustive.

search_text.total_matches is retained for compatibility. Shaping such as files_with_matches, collapse_by_file, or per-file caps can make the authoritative completeness unit differ from raw occurrence count.

Canonical continuation values are opaque. They bind:

  • the tool name;
  • the session;
  • the normalized original request;
  • repository scope;
  • repository snapshot state.

Replay the original request unchanged and set only the returned continuation. Do not decode, edit, or transfer a token across sessions.

Error Meaning Recovery
STALE_CONTINUATION The repository snapshot changed. Re-run the original tool without a continuation.
CONTINUATION_SCOPE_MISMATCH Tool, request, repository, or session does not match. Repeat the exact request or start a fresh search.
MIXED_CONTINUATION_FORMS Both legacy resume_from and canonical continuation were sent. Keep only continuation.

Legacy resume_from remains on a few tools for compatibility. New clients should store only completeness.continuation.

Proof-producing searches, outlines, and navigation tools can return:

  • response-level result_handle;
  • row-level match_id;
  • handle_scope and handle_expires="session".

The pair identifies source observed by the producer. Handles are session-scoped and revision-bound; they are not durable citations or authorization tokens.

Call read_match with the pair to obtain bounded proof. Frigg validates current source against the captured identity and refuses stale or mixed evidence:

  • STALE_HANDLE
  • MIXED_HANDLE
  • STALE_PROOF_ANCHOR

After an edit, re-run producers for touched paths. Use read_file only when current live source, rather than proof of the earlier result, is the intended evidence.

Rows may also carry a strict executable identity:

  • result_match: result_handle, match_id, and opaque target_scope;
  • stable_symbol: repository_id, stable_symbol_id, and snapshot_token.

Copy target_ref unchanged into a navigation or impact request. target_scope correlates the session and producer; it is not an authorization credential.

Important failures:

Error Meaning
CONFLICTING_TARGET_INPUT target was combined with legacy symbol or location fields.
TARGET_REPOSITORY_MISMATCH A repository assertion disagrees with the target.
TARGET_SCOPE_MISMATCH A result target belongs to another session or scope.
STALE_TARGET_SNAPSHOT A stable-symbol target names an obsolete snapshot.
TARGET_NOT_FOUND The identity is absent from the active repository.
TARGET_ANCHOR_INSUFFICIENT The target does not contain enough exact location information.

Frigg always navigates current source. It never follows a target into historical bytes.

Recovery and proof responses can include canonical next_actions[]:

{
"id": "verify-exact-1",
"role": "verify_exact",
"order": 20,
"dependencies": [],
"tool": "search_text",
"arguments": { "query": "FriggMcpServer" },
"reason": "Verify the discovered identifier with exact text search."
}

Roles are retry, broaden_scope, resolve_target, verify_exact, proof_read, inspect, and diagnose. Dependency groups use all or any over earlier action IDs. Responses contain at most eight normalized actions.

Each action names a public tool and schema-valid arguments. The client still invokes it through normal MCP authorization; Frigg has no generic executor and does not auto-chain actions. Actions unavailable on the live filtered surface are omitted.

suggested_next is a deprecated, lossy compatibility projection. Prefer next_actions whenever both appear.

Compact responses retain the flattened recovery grammar:

  • error_code and message
  • correction_hint
  • related_tools
  • next_actions
  • zero_hit_reason
  • applied scope
  • index and freshness diagnostics

Zero-hit reasons include indexed_search_complete, wrong_repository_possible, path_class_not_indexed, scope_excluded_all_candidates, index_stale_possible, query_looks_like_regex, tool_unavailable, precise_graph_unavailable, no_index_coverage, index_not_ready, and query_miss.

Transport failures also include structured MCP data. Read data.error_code and data.retryable rather than branching only on the top-level JSON-RPC code. Invalid parameters, missing resources, access denial, and storage incompatibility are non-retryable without correction; timeout and strict semantic unavailability can be retryable.

See troubleshoot MCP results for recovery procedures.

  • ../frigg/crates/cli/src/mcp/types.rs
  • ../frigg/crates/cli/src/mcp/types/completeness.rs
  • ../frigg/crates/cli/src/mcp/types/target.rs
  • ../frigg/crates/cli/src/mcp/types/next_action.rs
  • ../frigg/crates/cli/src/mcp/types/recovery.rs
  • ../frigg/crates/cli/src/mcp/server/presentation.rs
  • ../frigg/crates/cli/src/mcp/server/next_actions.rs
  • ../frigg/crates/cli/src/mcp/server/errors.rs