Documentation
¶
Overview ¶
Package provider is the Section 11.1 provider runtime: the contract every fact producer implements, the registry that orders and selects providers, the byte- and record-bounded sink their output flows through, and the one place a unit is sealed or discarded.
A provider emits small immutable units with explicit inputs, never a mutable global graph. The coordinator (internal/index) assigns scope, source view, reservations and dependencies; the sink stages bounded batches through storage's UnitWriter; storage validates and seals; only a sealed unit can be a generation member. Failed unsealed output is deleted and can never be queried. There is no plugin framework here and no second process abstraction: an external tool runs through internal/process.
Index ¶
- Constants
- func AliasBytes(a model.NativeAlias) int64
- func CodeOf(err error) string
- func NodeFactBytes(f model.NodeFact) int64
- func RelationFactBytes(f model.RelationFact) int64
- func RunUnit(ctx context.Context, p Provider, req UnitRequest, out UnitOutput, ...) (model.ProviderResult, error)
- func SearchUnitBytes(u model.SearchUnit) int64
- type BatchSink
- func (s *BatchSink) Bytes() uint64
- func (s *BatchSink) Degradations() []Degradation
- func (s *BatchSink) Discard()
- func (s *BatchSink) Flush(ctx context.Context) error
- func (s *BatchSink) PutAliases(ctx context.Context, aliases []model.NativeAlias) error
- func (s *BatchSink) PutKeyedNodes(ctx context.Context, facts []model.NodeFact, keys [][]string) error
- func (s *BatchSink) PutKeyedRelations(ctx context.Context, facts []model.RelationFact, keys [][]string) error
- func (s *BatchSink) PutNodes(ctx context.Context, facts []model.NodeFact) error
- func (s *BatchSink) PutRelations(ctx context.Context, facts []model.RelationFact) error
- func (s *BatchSink) PutSearchUnits(ctx context.Context, docs []model.SearchUnit) error
- func (s *BatchSink) Records() uint64
- func (s *BatchSink) Reserve(ctx context.Context, n int64) (release func(), err error)
- type Degradation
- type DeltaSink
- type Detection
- type Limits
- type Pool
- type Provider
- type Registry
- type Resolver
- type Selection
- type Sink
- type UnitOutput
- type UnitRequest
Constants ¶
const MaxDetectionInputs = model.MaxRecordsPerResult
MaxDetectionInputs bounds Detection.InputPaths. Detection names the inputs a provider recognized (manifests, index files), not the repository's file list; a provider that recognizes more than this reports the bound, not the list.
const MaxLiveSinks = 1024
MaxLiveSinks bounds the sinks one pool tracks at a time. The coordinator runs far fewer units concurrently; the bound exists so the registry is finite, not to size it.
const ScopeWorkspace = "workspace"
ScopeWorkspace is the capability scope the registry reports for a provider that produced no unit at all: disabled, unavailable or failed before it ran.
Variables ¶
This section is empty.
Functions ¶
func AliasBytes ¶
func AliasBytes(a model.NativeAlias) int64
AliasBytes is the retained-byte estimate of one native alias.
func CodeOf ¶
CodeOf extracts the Section 22 code an error carries for a diagnostic column: the typed code when there is one, CTX_CANCELED for a bare context end (a cancellation is never recorded as a provider crash) and CTX_INTERNAL otherwise. A nil error has no code.
func NodeFactBytes ¶
NodeFactBytes is the retained-byte estimate of one node fact: every string of the node, the canonical key and the evidence.
func RelationFactBytes ¶
func RelationFactBytes(f model.RelationFact) int64
RelationFactBytes is the retained-byte estimate of one relation fact.
func RunUnit ¶
func RunUnit(ctx context.Context, p Provider, req UnitRequest, out UnitOutput, limits Limits, pool *Pool) (model.ProviderResult, error)
RunUnit executes one assigned unit end to end: it runs the provider with a batch sink over out, flushes what the provider emitted, and seals the unit only when the provider reported a succeeded run and the writer's whole-unit validation passed. On a partial run or a write failure the unit is failed and its output deleted. A build the caller cancelled abandons the unit instead: it is marked failed and its rows are left for storage's collection, so the exit path never waits on a rollback. Failed or abandoned output is never attached to a generation.
The provider runs under a child context that the sink cancels when a write fails, so every producer goroutine stops promptly. Cleanup uses a context that survives that cancellation. The returned result always names req.Run and a terminal state; the error explains a non-succeeded state.
The writer behind out is single-owner: it has no lock of its own, and Seal and Fail must never overlap a write. While the sink is live another acquirer may flush its queued batches into the writer to relieve pool pressure, so the sink is discarded (which waits for any such write and then leaves the pool) before Seal, Fail or Abandon is called on any path. The deferred Discard is only the idempotent safety net.
func SearchUnitBytes ¶
func SearchUnitBytes(u model.SearchUnit) int64
SearchUnitBytes is the retained-byte estimate of one search document.
Types ¶
type BatchSink ¶
type BatchSink struct {
// contains filtered or unexported fields
}
BatchSink is the Sink handed to a provider for one unit. It owns every record from acceptance until the destination has persisted it: a record is admitted only after its bytes are charged to the pool, a batch flushes as soon as the next record would exceed either limit, and a failed write latches the sink, discards every queued batch (returning its bytes) and cancels every producer of the unit. Nothing here reaches the database except through the destination, which in production is storage's UnitWriter. It is safe for concurrent use by a provider's workers; writes to the destination are serialized. The owner must call Discard when the unit is finished, whatever the outcome; RunUnit does.
func NewBatchSink ¶
func NewBatchSink(ctx context.Context, dst Sink, limits Limits, pool *Pool, cancel context.CancelCauseFunc) (*BatchSink, error)
NewBatchSink binds a sink to its destination, limits and shared pool and registers it with the pool. ctx is the unit's run context; it is the context under which another acquirer may flush this sink's queued batches to relieve pool pressure. cancel is invoked with the write error when a required write fails, so every goroutine producing into this unit observes cancellation.
func (*BatchSink) Degradations ¶
func (s *BatchSink) Degradations() []Degradation
Degradations reports every bound this unit's records exceeded. It is empty for a unit that stayed within the bounds the user set, which is every unit under the shipped defaults, because no default bounds a record's size.
func (*BatchSink) Discard ¶
func (s *BatchSink) Discard()
Discard ends the sink: whatever is still queued is dropped and its bytes returned to the pool in one release, and the sink leaves the pool's live set. It is idempotent and a no-op after a successful Flush left nothing queued. The owner calls it on every path so a provider that erred or was canceled with records queued never shrinks the pool for the rest of the run.
func (*BatchSink) Flush ¶
Flush persists every queued batch in reference order: nodes first, because relation, alias and search rows reference node identities the same unit may have minted; then relations, aliases and search documents.
func (*BatchSink) PutAliases ¶
PutAliases accepts native aliases.
func (*BatchSink) PutKeyedNodes ¶
func (s *BatchSink) PutKeyedNodes(ctx context.Context, facts []model.NodeFact, keys [][]string) error
PutKeyedNodes accepts node facts with the producer's delta keys.
func (*BatchSink) PutKeyedRelations ¶
func (s *BatchSink) PutKeyedRelations(ctx context.Context, facts []model.RelationFact, keys [][]string) error
PutKeyedRelations accepts relation facts with the producer's delta keys.
func (*BatchSink) PutNodes ¶
PutNodes accepts node facts. Batches are sorted by node ID before they are written so the transaction shape is a function of content, not of the order workers finished.
func (*BatchSink) PutRelations ¶
PutRelations accepts relation facts.
func (*BatchSink) PutSearchUnits ¶
PutSearchUnits accepts search documents.
func (*BatchSink) Records ¶
Records and Bytes report what the sink accepted so far, for the provider's run counters.
func (*BatchSink) Reserve ¶
Reserve charges n bytes against the pool before a provider decodes or buffers input of that size, blocking until the reservation fits and returning promptly on cancellation. The returned release must be called exactly once. A reservation over a user-set MaxRecordBytes is counted as a degradation and then made: the pool is what bounds what the run holds, and refusing here would fail the unit over a bound the user set to be told about. A reservation larger than the whole pool is still refused by Pool.acquire, which names the reservation that is too small.
type Degradation ¶
type Degradation struct {
// Limit is the configuration key whose user-set value was exceeded.
Limit string
// Bound is the value the user set.
Bound int64
// Count is how many records and reservations exceeded it.
Count uint64
// Largest is the largest size observed over the bound.
Largest int64
}
Degradation is the sink's one degradation surface: a bound a unit's records exceeded, counted, so that exceeding it is reported rather than failing the unit. It is the sink's equivalent of the dropped-and-counted rows the bundled providers already publish, and RunUnit folds it into the unit's capability rows as bounded details the generation stores.
type DeltaSink ¶
type DeltaSink interface {
Sink
PutKeyedNodes(ctx context.Context, facts []model.NodeFact, keys [][]string) error
PutKeyedRelations(ctx context.Context, facts []model.RelationFact, keys [][]string) error
}
DeltaSink is the optional extension of Sink for a provider that imports incrementally (Section 11.4). Its destination records, alongside each fact, every one of the producer's own id-independent keys — the keys the provider's next run classifies as changed, unchanged or removed. Storage needs them because a removed fact cannot be named any other way: a fact identity is derived from the resolved entities, which an edit changes, and a cross-file edge can disappear while every file holding its evidence is untouched.
keys is either empty, meaning the batch carries no keys, or parallel to facts: keys[i] is every key backing facts[i] — at least one, each a lowercase hex digest, sorted and without duplicates. One fact is backed by several keys whenever the producer's keys are finer than the identities they resolve to, which is ordinary: a canonical edge is published once and derived from N occurrences, each with its own key. The destination drops the fact when any of them is replaced, which is the condition the producer re-emits the whole fact on.
A destination that does not implement DeltaSink cannot serve a keyed batch; the sink refuses it rather than dropping the keys, because a unit written without them silently cannot be delta-refreshed.
type Detection ¶
type Detection struct {
Available bool `json:"available"`
// DiagnosticCode is the Section 22 code explaining an unavailable result,
// for example CTX_TRUST_REQUIRED for an unapproved executable or
// CTX_PROVIDER_UNAVAILABLE for a tool that is not installed.
DiagnosticCode string `json:"diagnostic_code,omitempty"`
// Capabilities are the declared capabilities this provider can actually
// offer here; a subset of its descriptor's list.
Capabilities []string `json:"capabilities,omitempty"`
// InputPaths are the root-relative inputs detection recognized, bounded by
// MaxDetectionInputs.
InputPaths []string `json:"input_paths,omitempty"`
// ObservedVersion is the exact tool version detection observed for an
// external analyzer (for example the output of a trusted `--version`
// probe). It is empty for bundled providers. The coordinator folds it into
// UnitSpec.ProviderVersion so units are keyed by the tool that actually
// produced them; Descriptor() itself stays static.
ObservedVersion string `json:"observed_version,omitempty"`
// Details carry the machine-readable particulars of a detection that
// DiagnosticCode cannot hold, as bounded key/value pairs. A provider that
// covers several languages through several payloads is available as soon as
// one of them resolves, and then has no other place to say that another
// language's indexer is absent and why: it plans no unit for that language,
// so no capability row is ever produced for it either. One pair per
// affected input -- `details["rust-analyzer"] = "CTX_TOOL_OFFLINE"` --
// keeps that typed rather than silent.
Details map[string]string `json:"details,omitempty"`
// Reason is the one bounded phrase that says, in the product's own words,
// why a detection is unavailable. A diagnostic code alone names the
// category and not the finding -- CTX_PROVIDER_UNAVAILABLE on a
// repository whose projects simply sit in subdirectories reads as "this
// provider is broken or absent" -- and Details deliberately do not
// survive an unavailable detection, so this is where the finding goes.
// It is empty for an available detection, which has its rows to speak
// with.
Reason string `json:"reason,omitempty"`
}
Detection is a provider's answer to "can you run against this workspace". Available false with a DiagnosticCode is the honest optional-absence outcome of Section 11.1: a missing or unapproved tool is unavailable, which is distinct from a failure. Detection must not walk the whole repository into memory; it inspects declared inputs through the confined Root.
func (Detection) Validate ¶
func (d Detection) Validate(desc model.ProviderDescriptor) error
Validate enforces the detection shape against the provider's descriptor: bounded lists, a diagnostic code on every unavailable result and no capability the descriptor did not declare.
func (Detection) WithDetail ¶
WithDetail returns the detection with one bounded diagnostic pair added, so a provider can build its answer in one expression. It is model.CapabilityState.WithDetail in shape and in bound: values are truncated to model.MaxDetailBytes, the map is capped at model.MaxCapabilityDetails entries, an empty key and an overflowing new key are both dropped, and the map is copied rather than written through, because a Detection is a value type a caller may already have copied.
type Limits ¶
Limits are the per-batch bounds of Section 11.1: a batch is capped by both records and retained bytes, and flushes at whichever is reached first. MaxRecordBytes is resources.max_provider_record_bytes, and zero is unlimited: no shipped value refuses a record for being large. A record over a limit the USER set is admitted and REPORTED -- the sink counts it as a degradation the unit's capability rows carry -- because a size key names what the answer should tell the caller about, not what it should refuse. Nothing here is what bounds memory: the batch reservations and the pool are.
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool is the retained-byte reservation shared by every sink of one indexing run (index.queue_bytes). Queued records and outstanding decode reservations are both charged against it, so the bytes providers hold before persistence are bounded across concurrent units, not only per batch.
The pool also tracks its live sinks. An acquirer that cannot be charged first asks every live sink, its own included, to persist what it has queued, so one sink that has stopped producing cannot pin the pool with a half-filled batch while another starves.
type Provider ¶
type Provider interface {
Descriptor() model.ProviderDescriptor
Detect(context.Context, workspace.Root, workspace.Policy) (Detection, error)
IndexUnit(context.Context, UnitRequest, Sink) (model.ProviderResult, error)
}
Provider is one fact producer. Descriptor is static identity and scheduling contract; Detect inspects the workspace without indexing it; IndexUnit produces exactly the assigned unit through the sink.
Detect takes the confined workspace root and traversal policy rather than the sketch's `workspace.View`, which does not exist: Root is the only safe way to open a repository file and Policy is what decides eligibility.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is the validated provider DAG of Section 13.1. It is built once by the composition owner from the complete provider list; construction rejects a duplicate ID, a dependency on an unknown provider and a dependency cycle, because a coordinator that scheduled such a graph could report units as ready whose dependencies can never complete.
func NewRegistry ¶
NewRegistry validates every descriptor and the graph they form and returns the registry with its stable dependency order.
func (*Registry) Select ¶
func (r *Registry) Select(ctx context.Context, root workspace.Root, policy workspace.Policy, enablement func(providerID string) config.Enablement) (Selection, error)
Select runs trusted detection over the registry in dependency order. enablement reports the configured state of each provider ID; a provider the configuration does not know is treated as config.Enabled, which is what a required base provider is. Under config.Auto an unavailable detection is honest absence; under config.Enabled it is a failure of a requested capability. A detection error is a failure under either. A provider whose dependency is not active cannot run and takes the dependency's category. A required provider that ends inactive is returned as an error: no generation can be built without it.
type Resolver ¶
type Resolver interface {
Resolve(context.Context, model.NodeCandidate) (model.Resolution, error)
}
Resolver reconciles a provider candidate to canonical identity. The result depends only on the candidate and the set of sealed dependency units, never on scheduling (Section 9.4).
type Selection ¶
type Selection struct {
Active []Provider
States []model.CapabilityState
// Detections holds the validated Detection of every Active provider, by
// provider ID. The planner needs two things only a Detection carries --
// ObservedVersion, folded into UnitSpec.ProviderVersion, and InputPaths,
// which scope the SCIP profile units -- and must not re-run detection
// against the live checkout when the plan is about the pinned snapshot.
Detections map[string]Detection
}
Selection is the outcome of detection over one workspace. Active holds the providers that will run, in dependency order. States holds every capability row detection publishes, at ScopeWorkspace and one per declared capability: `unavailable` for an absent optional provider, `failed` for an enabled provider that could not be detected, and `partial` for a provider that *will* run but whose detection named something inside it that cannot (Detection.Details). The categories are kept apart because an optional tool that is absent must not make a healthy base generation falsely fail, while an enabled requested capability that fails makes the generation degraded (Sections 11.1, 13.3); a partial row is the middle case -- the provider runs, and the coordinator publishes the reasons the rest of it will not.
A provider the configuration disabled publishes NO row at all. `unavailable` is the record of work that was wanted and not attempted, each row carrying the reason it was not; nobody asked a disabled provider for anything, so it has nothing to report per capability, and a report full of `unavailable` rows for it reads as a degraded index rather than a configured one. That a provider is off is said once, by the coordinator, on the result and in the log -- not once per capability.
type Sink ¶
type Sink interface {
PutNodes(context.Context, []model.NodeFact) error
PutRelations(context.Context, []model.RelationFact) error
PutAliases(context.Context, []model.NativeAlias) error
PutSearchUnits(context.Context, []model.SearchUnit) error
}
Sink receives a unit's facts. Ownership of a handed-off slice transfers to the sink: the provider must not retain or mutate it afterwards. A call blocks while the sink's retained-byte reservation is exhausted and returns promptly on cancellation. A single record over a user-set resources.max_provider_record_bytes is admitted and counted as a degradation the unit's capability rows report; it never fails the unit. What bounds the heap is the batch reservation and the shared pool, not that key.
Hand a node fact to the sink before any relation, alias or search document that references its identity. Batch flush timing is not under the provider's control: a batch may be persisted at any call, including by another unit relieving pool pressure, and storage requires a relation's endpoints and an alias's target to be registered identities when the row is written.
type UnitOutput ¶
type UnitOutput interface {
Sink
Seal(context.Context) error
Fail(context.Context) error
Abandon(context.Context) error
}
UnitOutput is the storage side of one building unit: the writer the sink drains into, sealing after whole-unit validation, and discarding on failure. Seal is the only path to generation membership; Fail deletes every row the unit wrote so unsealed output can never be queried (Section 11.1). Abandon is the cancel-path discard: it gives up the unit without the cascading delete, leaving the rows for storage's own collection, which is what keeps an interrupt from waiting on a rollback nobody is going to read.
func StoreUnit ¶
func StoreUnit(store *sqlite.Store, w *sqlite.UnitWriter) UnitOutput
StoreUnit binds a building unit opened by store.BeginUnit.
type UnitRequest ¶
type UnitRequest struct {
Binding model.Binding
Unit model.UnitSpec
Run model.ProviderRunID
Content model.SnapshotView
Resolver Resolver
}
UnitRequest is one assigned unit of work. Binding is the staging generation the unit is built for; Unit is the immutable identity storage has already opened; Content is the pinned snapshot view every byte must be read from; Resolver reconciles candidates against the unit's completed dependencies.
Run is not in the Section 11.1 sketch. It is carried because every Evidence row must name the producing run (storage rejects evidence for another run) and ProviderResult.RunID must echo it; without it a provider could not build a single valid fact.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package dependence is the Section 11.6 dependence provider: call facts for the nine supported languages, produced by a managed code-property-graph engine that runs one frontend-native project at a time.
|
Package dependence is the Section 11.6 dependence provider: call facts for the nine supported languages, produced by a managed code-property-graph engine that runs one frontend-native project at a time. |
|
graphcsv
Package graphcsv imports one dependence-engine graph export into provider facts.
|
Package graphcsv imports one dependence-engine graph export into provider facts. |
|
graphengine
Package graphengine is the dependence provider's engine backend: the one place in the product that knows which code-property-graph engine produces the facts, what its command line looks like, how its heap cap is placed and what its diagnostics mean.
|
Package graphengine is the dependence provider's engine backend: the one place in the product that knows which code-property-graph engine produces the facts, what its command line looks like, how its heap cap is placed and what its diagnostics mean. |
|
Package filesystem is the base provider of Section 11.2: repository, directory, file and recognized document/configuration/build-target nodes, the `contains` and `defines` relations between them, the README-style `documents` relation, and the per-file lexical search chunks stored once in the file's own unit.
|
Package filesystem is the base provider of Section 11.2: repository, directory, file and recognized document/configuration/build-target nodes, the `contains` and `defines` relations between them, the README-style `documents` relation, and the per-file lexical search chunks stored once in the file's own unit. |
|
Package lsp is the snapshot-qualified working-tree overlay of Section 11.5: on-demand definition, references, implementations, type definition, document and workspace symbols and call hierarchy answered by an approved local language server running against a private materialization of the pinned snapshot.
|
Package lsp is the snapshot-qualified working-tree overlay of Section 11.5: on-demand definition, references, implementations, type definition, document and workspace symbols and call hierarchy answered by an approved local language server running against a private materialization of the pinned snapshot. |
|
Package manifest is the Section 11.2 build-metadata and documentation provider: package, module, dependency and configuration nodes parsed from go.mod, go.work, package.json, Cargo.toml, pyproject.toml and pom.xml, and the headings and source links of Markdown documents.
|
Package manifest is the Section 11.2 build-metadata and documentation provider: package, module, dependency and configuration nodes parsed from go.mod, go.work, package.json, Cargo.toml, pyproject.toml and pom.xml, and the headings and source links of Markdown documents. |
|
Package providertest is the shared provider conformance harness (Section 30.2).
|
Package providertest is the shared provider conformance harness (Section 30.2). |
|
Package scip is the Section 11.4 provider: streaming import of SCIP precise indexes and execution of the six pinned SCIP indexers (scip-go, scip-typescript, scip-python, scip-java, rust-analyzer and scip-clang) against a private materialization of the pinned snapshot.
|
Package scip is the Section 11.4 provider: streaming import of SCIP precise indexes and execution of the six pinned SCIP indexers (scip-go, scip-typescript, scip-python, scip-java, rust-analyzer and scip-clang) against a private materialization of the pinned snapshot. |
|
Package treesitter is the bundled structural provider of Section 11.3: a tree-sitter pass over each supported source file that publishes declarations, containing scopes, signatures, imports and exports, syntax references and call sites, test declarations and attached documentation at precision syntax, and, from the same worker walk, the file-local dependence families control_depends_on, data_flows_to, reads and writes between the file's parameters and locals at precision static_analysis (docs/providers-treesitter.md, Dependence facts).
|
Package treesitter is the bundled structural provider of Section 11.3: a tree-sitter pass over each supported source file that publishes declarations, containing scopes, signatures, imports and exports, syntax references and call sites, test declarations and attached documentation at precision syntax, and, from the same worker walk, the file-local dependence families control_depends_on, data_flows_to, reads and writes between the file's parameters and locals at precision static_analysis (docs/providers-treesitter.md, Dependence facts). |
|
flow
Package flow is the per-function dependence core: a language-neutral control-flow graph, its dominance relations, control dependence and SSA def-use.
|
Package flow is the per-function dependence core: a language-neutral control-flow graph, its dominance relations, control dependence and SSA def-use. |
|
lang
Package lang is the pinned language registry of the tree-sitter provider: the nine mandatory grammars of Section 11.3, the exact module version, grammar ABI and grammar metadata each one was reviewed at, the file extensions each grammar declares, and the embedded structural query pack.
|
Package lang is the pinned language registry of the tree-sitter provider: the nine mandatory grammars of Section 11.3, the exact module version, grammar ABI and grammar metadata each one was reviewed at, the file extensions each grammar declares, and the embedded structural query pack. |
|
wire
Package wire is the framed protocol between the tree-sitter provider and its parser worker subprocess.
|
Package wire is the framed protocol between the tree-sitter provider and its parser worker subprocess. |
|
worker
Package worker is the parser side of the tree-sitter provider: a subprocess that owns every native object (parser, tree, query, query cursor) and never touches storage, identities or the repository.
|
Package worker is the parser side of the tree-sitter provider: a subprocess that owns every native object (parser, tree, query, query cursor) and never touches storage, identities or the repository. |