Skip to content

Rust API

This page lists the public Rust surface of Bifrost 0.12.0. The Cargo package is brokk-bifrost and the crate name is brokk_bifrost. For a task-oriented introduction and the stability policy, see Rust Library.

Generate the complete item-level documentation for your dependency tree with cargo doc -p brokk-bifrost --open.

Every workspace package is published to crates.io at the same version. Keep every direct Bifrost dependency on the same version.

Cargo packageRust crateContents
brokk-bifrostbrokk_bifrostThe facade. Re-exports the supported API and builds the bifrost binary. Most applications depend on this package alone.
brokk-bifrost-corebrokk_bifrost_coreSource model, project, and workspace utilities shared by every other crate.
brokk-bifrost-analysisbrokk_bifrost_analysisThe protocol-neutral analysis engine: analyzers, the analyzer store, search tools, and usage analysis.
brokk-bifrost-rqlbrokk_bifrost_rqlRQL syntax, typed query IR, planning, and execution.
brokk-bifrost-flowbrokk_bifrost_flowDataflow, value-flow, taint, and typestate engines.
brokk-bifrost-policybrokk_bifrost_policyPolicy loading, evaluation, and reporting.
brokk-bifrost-semantic-packsbrokk_bifrost_semantic_packsThe shipped semantic-model packs and pack bundle installation. It also has a bifrost-semantic-pack binary that requires the release-tooling feature.
brokk-bifrost-runtimebrokk_bifrost_runtimeThe protocol-neutral runtime and the stable extension API.
brokk-bifrost-mcpbrokk_bifrost_mcpThe MCP server implementation and SearchToolsService.
brokk-bifrost-cppbrokk_bifrost_cppC and C++ language adapter.
brokk-bifrost-csharpbrokk_bifrost_csharpC# language adapter.
brokk-bifrost-gobrokk_bifrost_goGo language adapter.
brokk-bifrost-js-tsbrokk_bifrost_js_tsJavaScript and TypeScript language adapter.
brokk-bifrost-jvmbrokk_bifrost_jvmJava, Kotlin, and Scala language adapter.
brokk-bifrost-phpbrokk_bifrost_phpPHP language adapter.
brokk-bifrost-pythonbrokk_bifrost_pythonPython language adapter.
brokk-bifrost-rubybrokk_bifrost_rubyRuby language adapter.
brokk-bifrost-rustbrokk_bifrost_rustRust language adapter.

The minimum Rust version is 1.99, and the crates use the 2024 edition.

FeatureDefaultMeaning
pythonoffBuilds the PyO3 extension module bifrost_searchtools._native.
extension-moduleoffStops the build from linking libpython, which a Python extension needs. maturin enables it together with python. Do not enable it for an executable: the link fails.
test-supportoffRe-exports the test-only hooks of the implementation crates, for use in a downstream crate’s own tests. Never enable it in a shipped build.
release-toolingoffInternal. Benchmark and release artifact tooling.
randomized-hashoffInternal. A CI mode that seeds internal hash tables randomly.

The Python package’s build configuration enables python and extension-module. Ordinary library and CLI builds need no feature.

These are the public modules of brokk_bifrost.

ModuleStatus
extensionStable extension API with a negotiated version. See Extension API.
rql, sexpCodeQuery and RQL: the brokk-bifrost-rql crate, and its S-expression parser and formatter.
analyzer, searchtools, searchtools_render, navigation, usages, summary, symbol_rename, relevance, diff_analysis, cyclomatic_complexity_diff, code_quality, file_tools, compact_graph, model_context, workspace_documentAnalysis modules from brokk-bifrost-analysis.
cancellation, cache_db, cache_gc, git_file, gitblob, hash, panic_report, path_normalization, path_utils, process, profiling, schema_version, seam_profile, text_utils, utilSupport modules from brokk-bifrost-analysis.
flowThe brokk-bifrost-flow crate.
policyThe brokk-bifrost-policy crate.
semantic_packsThe brokk-bifrost-semantic-packs crate.
code_intelligenceHost implementation interface from brokk-bifrost-runtime. No compatibility guarantee.
searchtools_service, mcp_cli, mcp_common, mcp_core, mcp_diff, mcp_extended, mcp_registry, mcp_slopcop, mcp_text, rmcp_host, scoped_project, tool_argumentsMCP server implementation from brokk-bifrost-mcp.
benchmark, dataflow_differential, mcp_install, mcp_property_fuzzer, owasp_benchmark, reference_differential, repo_statusInternal harnesses for Bifrost’s own binaries and tests. Not part of the supported surface.
summary_foundry_fixtures, summary_foundry_demandInternal. Present only with the release-tooling feature.

These items are re-exported at brokk_bifrost::<name>.

ItemKindMeaning
WorkspaceAnalyzerenumA workspace analyzer with multi-language routing and an analyzer store. See WorkspaceAnalyzer Constructors.
MultiAnalyzerstructRoutes requests across per-language analyzers.
AnalyzerDelegateenumOne per-language analyzer inside a MultiAnalyzer.
EmptyAnalyzerstructThe analyzer for a project with no supported files.
IAnalyzertraitCommon analyzer operations: files, declarations, sources, summaries, and lookups.
TreeSitterAnalyzerstructThe shared tree-sitter analyzer implementation that each language analyzer wraps.
CppAnalyzer, CSharpAnalyzer, GoAnalyzer, JavaAnalyzer, JavascriptAnalyzer, KotlinAnalyzer, PhpAnalyzer, PythonAnalyzer, RubyAnalyzer, RustAnalyzer, ScalaAnalyzer, TypescriptAnalyzerstructsPer-language analyzers.
AnalyzerConfigstructAnalyzer settings. See AnalyzerConfig.
DispatchHierarchyExpansionstructWhich class-hierarchy expansions call dispatch adds. Constants OFF and CONCRETE_OVERRIDES.
AnalyzerDefinitionLookupstructA bounded forward-lookup view over an analyzer.
CapabilityProvidertraitGives access to an analyzer’s optional capability traits.
ImportAnalysisProvider, TypeHierarchyProvider, TypeAliasProvider, TestDetectionProvidertraitsOptional analyzer capabilities.
ImportReachabilityenumWhether a candidate file can reference a target declaration: Reaches, DoesNotReach (only from a complete proof), or Unknown.
collect_workspace_filesfunctionLists every file under a root that the analyzer considers part of the workspace. Respects ignore files and skips .git/.
ensure_global_rayon_poolfunctionConfigures the process-wide rayon thread pool. Safe to call more than once; the first call wins.
CancellationTokenstructA cloneable cancellation flag for long-running calls.
ItemKindMeaning
ProjecttraitA source of project files and their contents.
FilesystemProjectstructA project read from a directory. FilesystemProject::new(root) -> std::io::Result<Self>.
FileSetProjectstructA project with a fixed list of files. FileSetProject::new(root, rel_paths).
OverlayProjectstructWraps another project and serves in-memory buffers for some files.
MultiRootProjectstructA project over several directory roots.
TestProjectstructA small project for tests.
ProjectFilestructA file path inside a project root.
SourceContentstructThe text of one source file.
LanguageenumA supported source language.
CodeUnitstructA declaration: class, function, field, or module.
CodeUnitTypeenumThe coarse category of a CodeUnit.
CodeUnitIndexstructAn index of code units.
DeclarationInfo, DeclarationKindstruct, enumDeclaration details and kind.
ImportInfostructOne import statement.
NavigationOperationenumDeclaration or Definition.
ParseError, ParseErrorKindstruct, enumA tree-sitter parse error and its kind.
RangestructA source range.
CodeBaseMetricsstructWorkspace size metrics.
SummaryInput, RenderedSummary, summarize_inputsstruct, struct, functionRender summaries for a set of inputs.
CloneSmell, CloneSmellWeights, TestAssertionSmell, TestAssertionWeightsstructsCode-quality findings and their scoring weights.

A host supplies dependency evidence. Bifrost reads the named files and does not run build tools for these types.

ItemKindMeaning
RustAnalyzerConfig, RustDependencyApiEvidence, RustSelectedTarget, RustPackageApiArtifactstructsExact Cargo and rustdoc evidence for Rust dependencies.
resolve_rust_semantic_pack_dependencies, RustDependencyPackAdapterfunction, structValidate exact Rust dependency selections and prepare reusable semantic-model packs.
RubyAnalyzerConfig, RubyDependencyApiEvidence, RubyGemApiArtifactstructsExact Bundler and local gem archive evidence.
resolve_ruby_semantic_pack_dependencies, RubyDependencyPackAdapterfunction, structValidate exact Ruby dependency selections and prepare RBS, RBI, or source packs.
PhpAnalyzerConfig, PhpDependencyApiEvidencestructsComposer metadata and installed package trees under approved vendor roots. Bifrost never runs Composer or dependency code and opens no network connection.
resolve_php_semantic_pack_dependencies, PhpDependencyPackAdapterfunction, structValidate exact PHP dependency selections and prepare packs.
JvmAnalyzerConfigstructJVM settings: external_dependencies, dependency_discovery, and standard_library_discovery.
JvmExternalDependenciesstructartifact_paths, coordinates, repository_roots, and gradle_cache_roots.
JvmExternalArtifact, JvmMavenCoordinatestructsOne artifact path (with optional source artifact and coordinate) and one Maven coordinate (group_id, artifact_id, version).
JvmDependencyDiscoveryConfigstructmode, maven_executable, gradle_executable, timeout (default 30 seconds).
JvmDependencyDiscoveryModeenumDisabled, Metadata (default), OfflineBuildTools.
DependencyPackWorkspaceContextstructCaller-owned state needed to activate configured dependency packs. A workspace never opens a pack catalog unless the host supplies this.
DependencyPackEcosystem, DependencyPackEcosystemOutcome, DependencyPackActivationOutcomeenum, structsThe ecosystems a host can activate, and the result of one activation.
PythonSemanticModelWorkspaceContextstructWorkspace context for Python semantic models.
install_bifrost_semantic_model_packsfunctionfn() -> Result<(), String>. Registers the shipped semantic packs for the process. If BIFROST_OPEN_SEMANTIC_PACK_BUNDLE names a bundle directory, Bifrost installs that bundle instead whenever it opens a catalog for activation; an empty value or a bundle with no compatible pack makes that activation fail. Call it once before you build analyzers or a SearchToolsService. Without it, no shipped packs activate. Later calls return the first result.
open_pack_engine_profilefunctionfn() -> serde_json::Value. The pack-consumer profile of this build: engine version, build identity, model-set digest, supported schema versions, and capabilities. bifrost pack-engine-profile prints the same JSON.
BIFROST_VERSION&strThe facade package version.
BIFROST_BUILD_IDENTITY&strThe exact source revision embedded at build time. bifrost --build-identity prints it.
ItemKindMeaning
SearchToolsServicestructIn-process access to every Bifrost tool. See SearchToolsService.
SearchToolsServiceErrorstructcode: SearchToolsServiceErrorCode and message: String. Implements std::error::Error.
SearchToolsServiceErrorCodeenumInvalidParams, StaleWorkspaceGeneration { requested, current }, UnknownTool, DeadlineExceeded, Internal.
ToolOutputenumText(String) or Structured { structured: Value, rendered_text: Option<String> }.
ProjectChangeWatcher, ChangeDeltastruct, structThe file watcher that a watched service uses, and one batch of changes.
CodeQuerystructA parsed query. See CodeQuery Execution.
CodeQueryExecutionModeenumResults, Explain, Profile.
CodeQueryExecutionLimitsstructExecution limits for one query.
CodeQueryResponseenumResults(CodeQueryResult), Explain(CodeQueryExplain), or Profile(Box<CodeQueryProfile>). result() returns the ordinary result for Results and Profile.
CodeQueryExplain, CodeQueryProfilestructsVersioned explain and profile reports. See Explain and Profile CodeQuery.
execute_request, execute_request_with_limits, execute_request_with_cancellationfunctionsRun a CodeQuery against an analyzer.
CodeIntelligenceRuntimestructHost implementation interface that runs typed requests against one caller-owned workspace. No compatibility guarantee.

With the test-support feature, the facade also exports reset_rust_tree_parse_counters_for_test, rust_tree_parse_count_for_test, rust_tree_parse_request_count_for_test, and rust_tree_parsed_bytes_for_test.

AnalyzerConfig has public fields. AnalyzerConfig::default() reads two environment variables.

FieldTypeDefault
parallelismOption<usize>BIFROST_PARALLELISM if it is a positive integer, else the number of available CPUs.
memo_cache_budget_bytesOption<u64>256 MiB.
dispatch_hierarchy_expansionDispatchHierarchyExpansionconcrete_overrides is on when BIFROST_CHA_CONCRETE_OVERRIDES is set, and off otherwise.
rustRustAnalyzerConfigdefault
jvmJvmAnalyzerConfigdefault
csharpanalyzer::CSharpAnalyzerConfigdefault. assembly_paths lists extra assemblies to index.
js_tsanalyzer::JsTsAnalyzerConfigdefault
goanalyzer::GoAnalyzerConfigdefault
pythonanalyzer::PythonAnalyzerConfigdefault
rubyRubyAnalyzerConfigdefault
phpPhpAnalyzerConfigdefault

Every constructor takes project: Arc<dyn Project> and config: AnalyzerConfig, and returns Result<WorkspaceAnalyzer, StoreError>. Call analyzer() on the result to get &dyn IAnalyzer.

ConstructorStore
build_persisted(project, config)The repository’s persisted analyzer cache. Reuses stored facts across runs and collects the cache automatically. Fails if the project has no persistence root.
build_persisted_for_languages(project, config, &BTreeSet<Language>)Same cache. Runs only the parsers of the given languages.
build_persisted_without_automatic_gc(project, config)Same cache. Collects only when the host asks.
build_persisted_with_progress(project, config, progress) and build_persisted_without_automatic_gc_with_progress(project, config, progress)As above, with a progress callback.
build_persisted_with_tier_access(project, config)As build_persisted, and also returns a record of which information tiers the build read.
build_scoped_persisted(project, config)Shares stored facts with the full workspace but keeps an isolated file list for a partial project.
build_ephemeral_footgun(project, config)A temporary store that is deleted when the analyzer drops. Nothing is reused. Use it for tests, for a checkout you must not write to, or for cold-build measurement.
build_ephemeral_for_languages_footgun(project, config, &BTreeSet<Language>) and build_ephemeral_with_tier_access_footgun(project, config)Ephemeral variants.

Data and Trust Boundaries describes where the persisted cache lives and what it contains.

SearchToolsService runs the same tool implementations as the MCP server, in process. Call install_bifrost_semantic_model_packs() before you construct it.

All constructors return Result<SearchToolsService, String>, except new_unbound and new_unbound_manual, which return Self. Every service uses the persisted analyzer cache unless the row says otherwise.

ConstructorFile changesIndex build
new(root: PathBuf)A file watcher applies changes before each query.Before the constructor returns.
new_manual_persisted(root: PathBuf)Only update_paths and refresh apply changes.Before the constructor returns.
new_deferred(root: PathBuf)File watcher.On a background thread. The constructor returns at once.
new_deferred_manual(root: PathBuf)Only refresh and update_paths.On a background thread.
new_one_shot(root: PathBuf)None. For a process that answers one call and exits.Before the constructor returns.
new_one_shot_workspace_independent(root: PathBuf)None. For one diff tool call that reads only Git endpoints.Only if a call needs the workspace.
new_unbound(), new_unbound_manual()Watcher, or manual.After bind_client_workspace(root). Until then, analyzer tools return an error.
new_manual_persisted_for_project(project: Arc<dyn Project>, config: AnalyzerConfig)Manual. Cache collection only on request.Before the constructor returns.
new_manual_persisted_with_progress_for_project(project, config, progress)As above, with a progress callback.Before the constructor returns.
new_manual_scoped_persisted_for_project(project, config)Manual, over a partial project.Before the constructor returns.
new_manual_ephemeral_footgun_for_project(project, config)Manual. Uses an ephemeral store that is deleted when the service drops.Before the constructor returns.

Configuration methods, called on a new service:

MethodMeaning
with_diff_snapshot_object_dir(self, dir: PathBuf) -> SelfTrusted Git objects directory for immutable diff endpoints.
with_workspace_scaled_query_limits(self) -> SelfScales query_code execution limits to the analyzed source volume, as policy evaluation does.

Tool names and arguments are the same as the MCP tools, plus update_paths, list_symbols, and classify_test_files. See the MCP tools reference.

MethodReturnsMeaning
call_tool_value(&self, name: &str, arguments: Value)Result<Value, SearchToolsServiceError>Structured result as JSON.
call_tool_json(&self, name: &str, arguments_json: &str)Result<String, SearchToolsServiceError>Same, with JSON text in and out.
call_tool_output(&self, name: &str, arguments: Value, render_options: RenderOptions)Result<ToolOutput, SearchToolsServiceError>Structured result and rendered text. RenderOptions is in searchtools_render and has one field, render_line_numbers.
call_tool_output_with_cancellation(&self, name, arguments, render_options, cancellation: Option<&CancellationToken>)Result<ToolOutput, SearchToolsServiceError>Same, with cancellation.
call_tool_payload_json(&self, name, arguments_json, render_options)Result<String, SearchToolsServiceError>JSON text {"structured": ..., "rendered_text": ...}. The Python client uses this method.
query_code_result(&self, arguments: Value)Result<CodeQueryResponse, SearchToolsServiceError>Runs query_code and returns the typed response instead of JSON.
tool_is_workspace_independent(name: &str, arguments: &Value) -> boolboolAssociated function. True for tools that read only Git endpoints.
MethodMeaning
close(&self) -> Result<(), SearchToolsServiceError>Drops the session. Later analyzer calls fail.
request_cache_gc(&self) -> Result<(), SearchToolsServiceError>Forces a Git-reachability collection of the persisted cache and waits until it finishes.
active_workspace_root(&self) -> Option<PathBuf>The current workspace root.
analyzer_snapshot(&self) -> Result<Arc<WorkspaceAnalyzer>, String>The current workspace analyzer, for read-only use.
bind_client_workspace(&self, root: PathBuf)Binds an unbound service to a root. Returns the canonical root.
unbind_client_workspace(&self)Removes a bound root.
wait_workspace_ready(&self, cancelled: &dyn Fn() -> bool) and wait_workspace_ready_until(&self, cancelled, deadline: Option<Instant>)Wait for a deferred build to finish.
workspace_build_pending(&self) -> boolWhether a deferred build is still running.
evaluate_policy_inputs(&self, root, policy_inputs, options) and evaluate_policy_inputs_with_observer(...)Evaluate a policy batch against the service’s workspace.

The CodeQuery steps typestate, value_flow, and taint read a protocol, a plan, or a result that the host registered on this service. Registration is available only through these Rust methods. The CLI, the REPL, the MCP server, and the Python client never register anything, so in those surfaces these steps return an unresolved_protocol_reference, unresolved_value_flow_plan_reference, or unresolved_taint_result_reference diagnostic and no rows. A .rqlp policy runs these analyses without registration; see Static Analysis Policies.

MethodArgumentsReturns
register_query_protocolprotocol_ref: rql::ProtocolRef, expected_root: analyzer::semantic::ProcedureHandle, protocol: Arc<flow::typestate::CompiledProtocol>, bindings: Arc<flow::typestate::TypestateBindingPlan>Result<rql::ProtocolRegistrationOutcome, SearchToolsServiceError>
unregister_query_protocol&rql::ProtocolRefResult<bool, SearchToolsServiceError> (whether a registration was removed)
register_query_value_flow_planplan_ref: rql::ValueFlowPlanRef, plan: Arc<flow::value_flow::ValueFlowPlan>Result<rql::ValueFlowPlanRegistrationOutcome, SearchToolsServiceError>
unregister_query_value_flow_plan&rql::ValueFlowPlanRefResult<bool, SearchToolsServiceError>
register_query_taint_resultstaint_ref: rql::TaintResultRef, results: Vec<Arc<policy::ProductionTaintAnalysisResult>>Result<rql::TaintResultRegistrationOutcome, SearchToolsServiceError>
unregister_query_taint_results&rql::TaintResultRefResult<bool, SearchToolsServiceError>

The query refers to a registration by its reference string: protocol_ref in a typestate step, plan_ref in a value_flow step, and taint_ref in a taint step.

Registration outcomes:

OutcomeMeaning
InsertedA new registration was stored under the reference.
AliasedAn identical registration already existed under another reference. The new reference points to it.
UnchangedThe reference already names an identical registration.

Registering a different value under a reference that is already in use fails with InvalidParams. Each registration records the workspace generation. After the workspace changes, a query that uses it returns typestate_registration_stale, value_flow_registration_stale, or taint_registration_stale.

Reference format: namespace:name. Parse one with str::parse or build one with new(namespace, name).

RuleValue
Whole referenceAt most 192 bytes.
Namespace1 to 63 bytes.
Name1 to 128 bytes.
CharactersLowercase ASCII letters, digits, -, _, and .. The first and last character must be a letter or digit.

Limits per service, for each of the three kinds:

LimitProtocolsValue-flow plansTaint results
References (names, including aliases)256256256
Distinct registrations128128128
Retained bytesprotocols 4 MiB, binding plans 16 MiB, artifacts 64 MiBplans 64 MiB, artifacts 64 MiBplans 64 MiB, reports 64 MiB, artifacts 64 MiB
Results per registration256

Build a query from JSON with CodeQuery::from_json(&serde_json::Value) -> Result<CodeQuery, QueryError>, or from RQL text with CodeQuery::from_source(&str) -> Result<CodeQuery, String>. RQL text is limited to 64 KiB. CodeQuery::to_canonical_json() returns the canonical JSON form. The sexp module holds the S-expression parser (parse_sexp, parse_sexp_with_limits, parse_sexp_document_with_limits) and formatter (format_sexp_document) that RQL, RQLP, and Rune IR share.

FunctionSignature
execute_requestfn(analyzer: &dyn IAnalyzer, query: &CodeQuery) -> CodeQueryResponse
execute_request_with_limitsfn(analyzer: &dyn IAnalyzer, query: &CodeQuery, limits: CodeQueryExecutionLimits) -> CodeQueryResponse
execute_request_with_cancellationfn(analyzer: &dyn IAnalyzer, query: &CodeQuery, limits: CodeQueryExecutionLimits, cancellation: &CancellationToken) -> CodeQueryResponse
rql::executefn(analyzer: &dyn IAnalyzer, query: &CodeQuery) -> CodeQueryResult. Ignores execution_mode and always returns ordinary rows.

The execute_request functions honor the query’s execution_mode. They have no registrations, so typestate, value_flow, and taint steps report an unresolved reference. Use SearchToolsService::query_code_result for those.

CodeQueryExecutionLimits::default() values:

FieldDefault
max_scanned_files20,000
max_scanned_source_bytes128 MiB
max_fact_nodes2,000,000
max_pipeline_rows50,000
semantic (CodeQuerySemanticLimits)max_materialized_files 256, max_source_bytes 16 MiB, max_rows_per_dimension 1,000,000, max_retained_bytes 256 MiB, rows_per_dimension None
typestate (CodeQueryTypestateLimits)max_reached_rows 1,000,000, max_candidates 8,192, max_witness_steps 64, max_witness_expansions 4,096, max_total_witness_expansions 1,000,000, max_witness_bytes 64 MiB, solver_work engine default
value_flow (CodeQueryValueFlowLimits)max_retained_relations 262,144, max_retained_bytes 16 MiB, max_endpoints 50,000, max_witnesses 4,096, max_witness_steps 4,096, max_witness_expansions 16,384, max_witness_bytes 4 MiB, max_total_witness_steps 262,144, max_total_witness_expansions 1,048,576, max_total_witness_bytes 16 MiB, solver_work engine default
taint (CodeQueryTaintLimits)max_findings 50,000, max_projected_bytes 64 MiB, max_origins_per_finding 4,096, max_witnesses_per_finding 4,096, max_steps_per_witness 4,096, max_witness_bytes 4 MiB

Semantic source and row capacities bound resident admissions. Scans and traversal visits never refuse: receipts report their cumulative counts and largest per-root work balances separately from resident peaks. Cumulative counts include admissions plus work, so the same held-and-scanned bytes can count twice.

For the typestate, value-flow, and taint groups, a zero value or a value above the group’s hard maximum makes a query that uses that analysis return an invalid_plan diagnostic.

brokk_bifrost::extension (the same module as brokk_bifrost_runtime::extension) is the versioned API for independent applications. Types outside this module carry no compatibility promise.

ConstantValue
EXTENSION_API_VERSIONExtensionApiVersion { major: 1, minor: 1 }. Minor versions only add.
EXTENSION_RUN_MANIFEST_SCHEMA"2.0"
TYPESTATE_OPERATION"experimental.semantic.typestate"
MAX_RETAINED_SEMANTIC_GAP_REASONS16

PUBLISHED_OPERATIONS is the single list of what the API offers. ExtensionWorkspace::capabilities() reports it, and negotiation accepts exactly the operations whose support is Complete or Partial.

Operation idStabilitySupportEntry point
structural.querystablecompleteExtensionWorkspace::structural_query
experimental.semantic.control_flowexperimental since minor 0completeExtensionWorkspace::semantic_relations
experimental.semantic.value_dependenceexperimental since minor 0partialExtensionWorkspace::semantic_relations with SemanticRelationKind::ValueDependence
experimental.semantic.typestateexperimental since minor 1partialExtensionWorkspace::typestate_check

Partial limits coverage, not availability. The per-language rows of the capability report (LanguageCapabilityReport: control_flow, value_dependence, typestate) say where an operation is unavailable. Every response states its operation and stability in its metadata.

pub struct ExtensionCompatibility {
pub major: u16,
pub minimum_minor: u16,
pub maximum_minor: u16,
pub required_capabilities: Box<[ExtensionCapabilityId]>,
}

ExtensionCompatibility::default() is major 1, minors 0 to 0, no required capabilities. negotiate_extension_api(&ExtensionCompatibility) returns NegotiatedExtensionApi { version, capabilities } or one of these ExtensionCompatibilityError values:

ErrorCause
UnsupportedMajor { requested, supported }major is not 1.
InvalidMinorRange { minimum, maximum }minimum_minor is greater than maximum_minor.
TooNewMinor { requested, supported }minimum_minor is greater than 1.
MissingCapability(id)A required capability is not served.
DuplicateCapability(id)A capability is listed twice.
InvalidCapability(text)ExtensionCapabilityId::new rejected the text. Ids are non-empty and use lowercase ASCII letters, digits, ., _, and -.

Every request carries its own compatibility and expected_generation. structural_query, semantic_relations, and typestate_check negotiate again for each request. Every entry point returns ExtensionError::StaleGeneration when expected_generation is not the workspace’s current generation.

ExtensionWorkspaceOptions has public fields:

FieldTypeDefault from ExtensionWorkspaceOptions::new(root)
rootsVec<PathBuf>vec![root]. API version 1 requires exactly one root.
analyzer_configAnalyzerConfigAnalyzerConfig::default()
limitsExtensionLimitsExtensionLimits::default()
persistenceExtensionPersistenceModeEphemeral: an in-memory store discarded when the workspace drops. .persisted() selects Persisted, the repository’s persisted analyzer cache.

ExtensionWorkspace::open(options) reads every workspace file into memory and builds the analyzer. A file that is not valid UTF-8 is skipped and reported in open_diagnostics(). A file larger than limits.source_bytes fails the open. Errors are ExtensionWorkspaceError::InvalidRoots, Project, Analyzer, or Store (a persisted store could not be opened; there is no fallback to an in-memory store).

MethodReturns
generation()&WorkspaceGeneration, the identity that every request must name.
content_identity()&WorkspaceContentIdentity, a hash of the normalized source and analyzer configuration. Two roots with the same content and configuration have the same value.
capabilities()&ExtensionCapabilityReport: generation, per-language rows, and operation rows.
store()&ExtensionStoreReport: requested, engaged, cache_db (path when persisted), diagnostics.
open_diagnostics()&[ExtensionDiagnostic], files skipped at open.
open_tiers()ExtensionTierReport, the information tiers the open read.
describe()ExtensionWorkspaceDescription, all of the above plus the API version, in one serializable value.
structural_query(StructuralRequest, &ExtensionCancellation)Result<ExtensionOutcome<StructuralResult>, ExtensionError>
semantic_relations(SemanticRelationRequest, &ExtensionCancellation)Result<ExtensionOutcome<SemanticRelationSnapshot>, ExtensionError>
typestate_check(TypestateRequest, &ExtensionCancellation)Result<ExtensionOutcome<TypestateSnapshot>, ExtensionError>
map_observations(&ObservationDocument, &ExtensionCancellation)Result<ObservationMappingResult, ExtensionError>. Maps range and branch records from another tool onto workspace nodes.
execute(ExtensionRequest, &ExtensionCancellation)Result<ExtensionResponse, ExtensionError>. Dispatches any of the four requests above.

ExtensionError values are Compatibility, StaleGeneration { expected, actual }, InvalidRequest, and Execution.

RequestFields
StructuralRequestcompatibility, expected_generation, query: CodeQuery, limits: ExtensionLimits. Serializes as a four-element array with the query in canonical JSON. StructuralResult has items: Box<[serde_json::Value]>, one CodeQuery row each.
SemanticRelationRequestschema_version, compatibility, expected_generation, seeds (Source { span } or StableNode { id }), scope (Procedure, File, or BoundedCalls { max_call_depth }), relations (ControlFlow, Call, Return, ControlDependence, ValueDependence), direction (Outgoing, Incoming, Both), limits: SemanticRelationLimits.
TypestateRequestschema_version, compatibility, expected_generation, protocol (the protocol document as JSON), subject, events, terminals, scope (only Procedure is served), limits: TypestateLimits.
ObservationDocumentschema_version, compatibility, expected_generation, repository, subject, the observation records, and mapping limits.

ExtensionLimits::new(ExtensionLimitValues) rejects any zero value. ExtensionLimits::default() uses these values:

FieldDefault
result_items1,000
result_bytes8 MiB
diagnostics256
source_bytes16 MiB
semantic_nodes10,000
semantic_edges20,000
semantic_files128
traversal_steps1,000,000
call_depth8

For structural_query, result_items caps rows, source_bytes caps scanned source bytes, and semantic_files caps scanned files. SemanticRelationLimits can be built from ExtensionLimitValues with From.

ExtensionCancellation::new() creates a token. cancel() stops the work, and a cancelled request returns completion Cancelled.

ExtensionOutcome<T> has completion: ExtensionCompletion, value: Option<T>, and metadata: ExtensionResultMetadata. The metadata holds api, operation, stability, generation, diagnostics, work, tiers, limits, and provenance.

ExtensionCompletionMeaning
CompleteThe answer is complete.
AmbiguousMore than one answer is possible.
UnknownThe analysis could not decide.
Unsupported { capability }The operation is not available here.
UnprovenThe returned items are proven, but the absence of other items is not proven.
Truncated { limit }A caller limit stopped the work. limit names it, so the caller knows which value to raise.
FrontierBounded { kinds }The analysis reached an edge of what it can know while every caller limit still had room. Larger limits give the same answer.
ExceededBudget { dimension }A budget was exhausted. dimension names it.
CancelledThe caller cancelled the request.

ExtensionTierReport counts tier crossings: syntax (file parses), imports (import reads), supertypes (supertype reads), and usage_graph (usage index builds). Zero means the tier was not consulted.

FunctionMeaning
decode_request_json(&[u8]) -> Result<ExtensionRequest, ExtensionDecodeError>Decode a request.
encode_request_json(&ExtensionRequest) -> Result<Vec<u8>, ExtensionEncodeError>Encode a request.
encode_response_json(&ExtensionResponse) -> Result<Vec<u8>, ExtensionEncodeError>Encode a response.

ExtensionRequest and ExtensionResponse serialize as {"operation": "structural" | "semantic_relations" | "typestate" | "observations", "request" | "response": ...}. The module also has per-type codecs: encode_relation_request_json, decode_relation_request_json, encode_relation_snapshot_json, decode_relation_snapshot_json, write_relation_snapshot_jsonl, read_relation_snapshot_jsonl, encode_typestate_request_json, decode_typestate_request_json, encode_typestate_snapshot_json, decode_typestate_snapshot_json, encode_observation_document_json, decode_observation_document_json, encode_observation_result_json, decode_observation_result_json, write_observation_mapping_jsonl, and read_observation_mapping_jsonl.

The module also describes extension runs so that another machine can check them. RunManifestBuilder builds an ExtensionRunManifest (schema 2.0) from a workspace. encode_run_manifest_json, decode_canonical_run_manifest_json, and decode_and_canonicalize_run_manifest_json serialize it. verify_extension_bundle(root, BundleVerificationLimits) checks a bundle directory and returns a VerifiedExtensionBundle. plan_reproduction compares a verified bundle with the local environment and returns a ReproductionMismatchReport when they differ. execute_reproduction runs the plan into a new destination directory.

use brokk_bifrost::extension::{
CodeQuery, ExtensionCancellation, ExtensionCapabilityId, ExtensionCompatibility,
ExtensionLimits, ExtensionWorkspace, ExtensionWorkspaceOptions, StructuralRequest,
negotiate_extension_api,
};
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let compatibility = ExtensionCompatibility {
major: 1,
minimum_minor: 0,
maximum_minor: 1,
required_capabilities: Box::new([ExtensionCapabilityId::new("structural.query")?]),
};
let negotiated = negotiate_extension_api(&compatibility)?;
println!("api {}.{}", negotiated.version.major, negotiated.version.minor);
let workspace = ExtensionWorkspace::open(ExtensionWorkspaceOptions::new(".").persisted())?;
let query = CodeQuery::from_json(&json!({
"match": { "kind": "function", "name": "run" }
}))?;
let outcome = workspace.structural_query(
StructuralRequest {
compatibility,
expected_generation: workspace.generation().clone(),
query,
limits: ExtensionLimits::default(),
},
&ExtensionCancellation::new(),
)?;
println!("completion: {:?}", outcome.completion);
if let Some(result) = outcome.value {
for item in result.items.iter() {
println!("{item}");
}
}
Ok(())
}