Adapters translate explicit native artifacts or staged capture outputs into typed evidence blocks. They do not discover projects, open repositories, publish evidence, install providers, or own job lifecycle.
Each operation registry entry owns:
- the operation descriptor and canonical task name;
- accepted source modes and formats;
- a strict validation-equivalent argument model;
- compatibility rules derived from declared artifact formats;
- capture and analysis handlers;
- model-visible selection guidance, bounded examples, limits, overhead, and limitations.
One immutable capture-provider contract owns each provider's argument model, declared artifact roles and formats, and selection description. Generated MCP schemas, pre-execution compatibility checks, and capture argument validation consume that same contract so their format claims cannot drift.
Adding or removing a format is complete only when these surfaces agree:
- the operation's accepted formats;
- the capture-provider contract and invocation builder, when capture is supported;
- explicit-path suffix detection;
- analysis dispatch into the provider or isolated worker;
- generated MCP analysis and capture schemas;
- the support table below.
Tests exercise explicit-path analysis and, when applicable, capture through the public runtime. A parser or worker that is not reachable through a declared operation is either intentionally internal and documented as such, or an incomplete registration—not latent support.
Operation tools remain discoverable when a provider is absent. Before dispatch, capture validates
typed arguments, declared format compatibility, and the selected executable or package binding.
Provider-specific version and resource checks run where implemented; there is no universal
permission or hardware preflight. Permissions, hardware availability, and target compatibility can
still fail when the upstream collector starts. Started attempts retain execution provenance.
An unavailable provider returns a typed result with either an exact prepare_providers retry
action or external host guidance.
SARIF analysis accepts an explicit absolute source_root in its options when the
report is exported outside the source tree. Paths and include/exclude filters are
normalized against that root without reading source contents. Outside-root paths,
traversal, remote URIs and unsupported URI bases remain rejected. If omitted, the
artifact's analysis directory remains the default; use an explicit root for replay.
The registry covers CPU profiles, memory profiles, benchmarks, inference exports, execution traces, GPU launches and kernel metrics, correctness and sanitizer failures, coverage, static candidates, and bounded generic previews. Artifact analysis and typed capture are separate contracts:
| Evidence family | Explicit artifact analysis | Typed capture provider |
|---|---|---|
| CPU profiles | Node/V8, cProfile pstats, py-spy Speedscope, perf collapsed stacks, perf data | node-cpu-profile, py-spy, perf |
| CPU caller edges | cProfile pstats, py-spy Speedscope | py-spy |
| Memory profiles | Memray, Node/V8 sampling heap profiles | memray, node-heap-profile |
| Benchmarks | pyperf, benchmark samples, PyTorch samples, NVBench | pyperf, benchmark-samples, nvbench |
| Execution traces | Perfetto/Chrome, PyTorch, OTLP, ROCprof PFTrace, xctrace, Nsight Systems | torch-profiler, rocprofv3, xctrace, nsight-systems |
| GPU and kernels | Nsight Systems, Nsight Compute, Compute Sanitizer, Triton, kernel validation | nsight-systems, nsight-compute, compute-sanitizer, triton |
| Reliability | pytest events, observations, coverage.py | pytest, observations, coverage |
| Static candidates | SARIF | — |
| Inference exports | AIPerf, vLLM, SGLang, Mooncake | — |
| Generic previews | JSON, JSONL, CSV, text, Parquet | direct process output |
An em dash means callers provide an explicit artifact path; it does not mean the format is unsupported. The offline inference readers omit prompts, generations, error text, endpoints, tools, payloads, and prefix-hash values.
CPU hotspot metric selection applies only to pstats. Node, py-spy, and perf captures reject an explicit metric before running the workload; omit it to use the native fixed weight. Saved artifacts can be reanalyzed with corrected arguments without rerunning capture.
V8 CPU and heap hotspot rows include their extracted function, file, frame identity,
symbolization state, and native zero-based line/column coordinates. Omitted coordinates
use -1 for unavailable; explicitly exported zero remains a valid first line or column.
Source maps are not resolved. CPU counts use exported sample node IDs rather than optional
hitCount metadata. Inclusive CPU counts sum call-tree occurrences and can repeat recursive
frames. Heap sample_count counts native allocation sample records per
frame, including records from multiple call-tree nodes with the same identity. self_value
and inclusive_value retain V8's allocation estimates, independently of sample counts. V8 and
SARIF extraction use literal object keys and distinct array locations; dotted keys cannot
impersonate native nodes, samples, or results. Malformed V8 child containers and duplicate
object fields fail decoding.
By default, Node capture uses Node's generated filenames, which include process and thread IDs,
so forked processes and profiled workers do not overwrite each other's output. Each CPU or heap
profile is preserved as a separate artifact with its original filename in the capture role.
Up to 32 profiles of the same V8 format can be ranked together; rows retain their artifact_id
and frame weights are not merged across profiles. Counts sum the admitted profiles, with a
profile_count metric for multiple inputs. This covers only processes and threads that emit
profiles with inherited flags; arbitrary descendants are not automatically profiled. Termination
can prevent Node from flushing a profile; completed files remain available from failed captures.
Native heap samples can reference nodes absent from the exported call tree. Those samples
remain in the total counts and estimated bytes, with separate unresolved_sample_count and
unresolved_sampled_bytes metrics, incomplete coverage, and an explicit attribution limitation.
inspect_triton_autotune reads native *.autotune.json caches (triton-cache) emitted
by Triton's cache_results=True, and listener events.
Native timing values retain producer order, including positive-infinity sentinels;
they are not averaged as repeated samples. The best configuration is derived
using Triton's lexicographic comparison. Native caches do not prove cache hits,
device identity, semantic correctness, or representative performance improvement.
The inspect_triton_autotune capture request uses Triton 3.7 in the declared workload interpreter.
It sets TRITON_CACHE_AUTOTUNING=1 and a fresh request-owned TRITON_CACHE_DIR,
preserving the native cache bundle, including compilation artifacts. This is a
cold-cache tuning experiment, not a warm-cache benchmark. Kernels must already
use Triton's autotuner; Flameox does not invent configurations or patch kernels.
An emitted cache without autotune records produces an explicit analysis failure.
Pytest capture runs an explicit python -m pytest target with a request-bound,
bounded event plugin.
Capture checks that pytest 8.3 or newer is available in that exact workload
interpreter before invoking the collector; installing pytest in the server
interpreter alone does not satisfy this requirement.
summarize_failures scans the complete bounded pytest event artifact for aggregate outcomes, but its
table projects only failed, errored, interrupted, and unexecuted identities. Failed collection
reports retain their collector identity; successful collection events, passing tests, and skipped
tests cannot consume the diagnostic row budget.
Native event readers bound each line before parsing: 64 KiB for pytest and 16 KiB for SDK
observations. Observation imports share the SDK's label and value bounds: names and non-null phases
contain 1–200 characters, values nest at most eight levels, and each collection has at most 256
entries. Timestamps are integers, excluding booleans. Text must be valid Unicode encodable as UTF-8,
including labels and object keys. Non-finite values, invalid Unicode, excessive nesting, and
oversized records produce DECODE_FAILURE; they do not become successful evidence or CLI tracebacks.
Support is honest rather than substitutive. A missing Trace Processor does not
turn a Perfetto request into a JSON preview; a missing ncu does not become an
empty kernel report.
Handlers receive resolved paths, exact digests, explicit format/producer hints, provider arguments, and effective limits. They return typed observed/derived blocks, staged native outputs, coverage, truncation, and limitations. They never look up runs or mutable records.
Semantic selection happens before bounding. A provider must filter for the requested projection
before applying row, byte, or worker limits, and rows_observed, complete, and truncation must
describe that same projected population. A bounded prefix of unrelated native rows is not evidence
that the requested activity is absent. OTLP time windows apply their span predicate before resource
and scope rows consume the normalization budget; only owning context for retained spans is emitted.
Nsight Systems CUDA runtime, driver, and synchronization tables feed summarize_trace_operations.
inspect_gpu_launches selects device kernel and memory activity; CUDA API calls and profiler overhead
cannot establish that a GPU launch occurred. The native CUPTI_ACTIVITY_KIND_* table family
contains both host and device evidence and must not be selected as one accelerator population.
Projection identity includes every non-axis dimension that can distinguish a series, including device, dtype, variant, scope, and worker identity where applicable. Providers must not blend those series. When a composite native label is successfully decomposed into named dimensions, the raw label must not remain as a redundant identity that changes with the selected axis. NVBench retains its raw state label if any meaningful component cannot be decoded, repeats a key, or conflicts with native dimensions. Such labels remain distinct even when their decoded numeric dimensions match.
Numeric aggregation requires compatible semantic units. Providers normalize convertible units to one declared output unit before pooling and reject incompatible dimensions; for example, seconds and nanoseconds may become seconds, while bytes and elapsed time cannot share a CPU-hotspot total. Rows and metrics expose the normalized unit so consumers never have to infer it from the format.
Native selectors such as table families, event categories, and field names require a representative artifact or authoritative format fixture. Unmatched selectors stay incomplete or explicitly limited; they must not silently become complete negative evidence. Adding a projection also requires a regression check for sibling projections that share its reader or dispatch path.
Raw parser safety limits are independent from normalized output limits. In particular, V8 node and sample ceilings bound native traversal, while the hotspot row limit bounds the ranked aggregate projection. A partial SARIF document is likewise incomplete even when every parsed result fits in the returned table.
Native references are validated before aggregation. Sample-to-node, edge-to-frame, parent-to-child, and similar identifiers must resolve inside the same artifact unless the format explicitly defines an external reference. A syntactically valid but unresolved identifier is corrupt evidence, not an ignorable sample.
The runtime projects provider blocks into the RFC 8785 JSON domain before bounding or preservation. Native integers outside JSON's interoperable safe integer range are represented as exact decimal strings; they are never rounded or allowed to fail later during canonicalization.
Native inputs remain byte-for-byte unchanged. Capture outputs stay in bounded session scratch until explicit preservation. Large derived tables are immutable files inside an evidence bundle, not rows in a durable database.
When capture-time preservation is requested, native outputs are published independently of downstream normalization success. A decoder failure is retained as a typed analysis failure next to authoritative native bytes rather than causing the capture to disappear.
Unsafe or heavy decoders use the typed isolated-worker protocol and descriptor-bound reads. Workers receive only declared inputs and budgets. Conversions are cached for the server session by input digest and provider version.
Perf conversion accepts output only after perf script exits successfully. Its callchain parser
preserves complete demangled symbol text and explicit unknown frames, so unresolved leaves do not
transfer samples to callers. Failed or ambiguous decoder output is never installed in the session
conversion cache. A nonzero decoder exit reports at most 4 KiB of replacement-decoded stderr with
retained and omitted byte counts, plus its typed exit or signal termination.
Nsight Systems prefers parquetdir export. Flameox does not read or create a
Nsight SQLite export. Memray aggregation streams bounded records or uses
session-local in-memory DuckDB; it does not create a temporary SQLite database.
Its worker returns only frame identities and frame measurements consumed by the
provider. Scalar metrics travel in the typed worker result; native captures stay
authoritative. Timeout and RSS enforcement remain at the worker harness boundary.
An explicit flameox setup --provider ... invocation prepares the exact
version-pinned uvx environment returned in its launcher. The invocation's
provider list is complete; Flameox retains no provider inventory or setup receipt.
System and vendor packages remain externally installed. Setup creates no
project state and is not a prerequisite for explicit-path analysis.
Nsight Compute capture requires both the ncu executable and NVIDIA's vendor-shipped
extras/python/ncu_report.py reader. Flameox resolves both before workload execution and returns
external setup guidance if the installation is incomplete.
Provider ownership is explicit during capture. py-spy executes from a verified session binding
prepared independently with uvx --from py-spy==0.4.2, or from beside the server interpreter.
Preparation checks the collector version and binds its executable identity; later capture rechecks
that identity. A removed or changed uv cache entry requires preparation again. Capture never
silently installs dependencies or resolves managed collectors from request PATH.
In-process collectors, including coverage.py, PyTorch, and
Memray, must be installed in the declared workload interpreter; capture probes
that interpreter before execution and never substitutes Flameox's interpreter.
Pyperf command capture preserves multiline typed argv through a metadata-safe launcher because pyperf rejects newline characters in its display metadata. The launcher executes the original argv without shell parsing, but its startup is included in each command measurement; exact Flameox capture provenance remains authoritative for the requested argv.
Memray frame extraction applies record, frame, and aggregate bounds to the requested high-watermark or retained-end population. Allocation history contributes scalar byte/operation totals without producing unrelated frame rows; temporary-allocation projections are not computed. Summary totals remain independent of which supported frame population was requested.
OTLP encoding comes from native content rather than the artifact filename, including after
preservation relocates JSON into an extensionless payload. Ambiguous protobuf prefixes are
validated as protobuf when JSON decoding fails. SARIF's implicit source root is resolved into
effective analysis arguments, so preserved replay and continuation retain the same path scope.
Nsight Systems rows preserve colliding native table columns under value; the outer table
continues to identify the actual source table.
OTLP nonfinite double attributes remain distinguishable from strings as tagged
{"type":"double","value":"NaN"} (with "Infinity" or "-Infinity" for infinite values). Nested
attributes use the same projection; native integer attributes retain exact values.
SARIF candidate coordinates index the native result within each run. Compute Sanitizer marks coverage incomplete when host-stack frames are omitted, separately from omitted record counts.