BlackBeard.Argus.Core 0.1.1

dotnet add package BlackBeard.Argus.Core --version 0.1.1
                    
NuGet\Install-Package BlackBeard.Argus.Core -Version 0.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BlackBeard.Argus.Core" Version="0.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BlackBeard.Argus.Core" Version="0.1.1" />
                    
Directory.Packages.props
<PackageReference Include="BlackBeard.Argus.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BlackBeard.Argus.Core --version 0.1.1
                    
#r "nuget: BlackBeard.Argus.Core, 0.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BlackBeard.Argus.Core@0.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BlackBeard.Argus.Core&version=0.1.1
                    
Install as a Cake Addin
#tool nuget:?package=BlackBeard.Argus.Core&version=0.1.1
                    
Install as a Cake Tool

Argus

Stream diagnostics for geospatial entity feeds.

Argus taps a stream of 6DOF entity samples — position, attitude, linear and angular velocity — and emits structured, self-describing findings about what is wrong with it.

It has no idea what the entities are. That is deliberate: every judgement it makes is against a configured threshold or a mathematical invariant, never against domain knowledge, which is what makes it reusable across whatever is producing the stream.

Argus.Core      zero dependencies · netstandard2.0 · net8.0
Argus.Graphics  Core + Microsoft.Maui.Graphics · netstandard2.0
Argus.Testing   corruption-injection harness · netstandard2.0 · net8.0

Why looking at the map is not enough

The usual way to check a stream is to render it and look. That catches the faults that are easy to catch and misses the ones that matter, for four reasons worth stating precisely:

  1. The viewport shows part of the world. An entity that has moved outside it is not observed to be wrong; it is not observed at all.
  2. A one-tick anomaly does not survive to the next frame. At a typical update rate a corrupted sample is on screen for a few tens of milliseconds. Nobody sees it — and it still propagates into everything derived from consecutive positions.
  3. The eye checks continuity, not correctness. A smoothly moving entity looks right whether or not it is where the producer said it was.
  4. A map has no memory and no arithmetic. It cannot tell you that the smallest positional step in this stream became sixteen times coarser at 14:02.

And the deeper problem: when a stream originates from a serial protocol marshalled into structs and piped over a socket, the faults that dominate are faults of encoding and framing, not of physics — and those produce values that are entirely plausible. A frame read eight bytes off puts a longitude in the latitude field and a velocity in the altitude field. Every value is in range. The map draws it without complaint. The entity is simply not where it should be.

Argus exists so that two teams either side of a stream can argue from evidence rather than impressions — which is also why the core and its documentation are public. The team producing the stream can read the detector definition that generated a finding without needing access to anything.

See docs/corruption-taxonomy.md for what each fault looks like on the wire.


Quickstart

using Argus.Configuration;
using Argus.Contracts;
using Argus.Pipeline;
using Argus.State;

var options = new MonitorOptions();

// Deployment gates have no defaults. A detector without its gate reports NotEvaluable rather
// than inventing a number, so these are yours to set.
options.Thresholds.MaxTeleportDistanceMeters = 1000.0;   // absolute distance gate
options.Thresholds.MaxSpeedMetersPerSecond   = 300.0;    // rate gate — set both, see below
options.Thresholds.GroupOutlierRadiusMeters  = 50000.0;

var monitor = new EntityHealthMonitor(options);

// Once per tick, not once per entity.
GroupTickContext tick = monitor.CreateTickContext(samples, tickTimeUtc);

foreach (EntitySample sample in samples)
{
    EntityHealthReport report = monitor.Observe(sample, tick);

    foreach (HealthFinding finding in report.FlaggedFindings())
    {
        Console.WriteLine(finding);
        // Teleport: measured 12043.2 m, expected at most 1000 m - The entity moved further
        // between consecutive samples than the absolute distance gate permits, regardless of
        // how much time elapsed.
    }
}

Every finding carries the flag name, a one-line definition, the measured value and the expected value or range. That redundancy is the point: a finding has to be readable by somebody who cannot look up what the flag means.

Set both gates

MaxTeleportDistanceMeters and MaxSpeedMetersPerSecond are not alternatives.

  • An absolute distance gate catches a slow entity that jumps across a tick boundary, and misses a fast entity drifting steadily.
  • A rate gate does exactly the inverse.

Neither subsumes the other. Configure both.

Three outcomes, not two

A detector returns Flagged, Healthy, or NotEvaluable — the last when a field it needs was not supplied or a threshold it needs is not configured. It is never reported as healthy. "We did not check" and "we checked and it was fine" are different claims, and a report that conflates them invites the reader to conclude something was verified when it was not.

if (report.IsHealthy && report.IsFullyEvaluated) { /* actually verified */ }

Conditions are not mutually exclusive

HealthFlags is a [Flags] enum and detection never suppresses. An entity can be a group outlier and have jumped and carry a non-normalised quaternion — and the three together are a far more specific diagnosis than any one of them. Presentation reduces that set to a single colour, by explicit severity precedence, in Argus.Graphics and nowhere else.


Corruption injection

Argus.Testing damages a synthetic stream the way a wire actually does — reversing bytes, shifting field offsets, rescaling fixed-point integers, dropping and reordering frames — so detectors are tested against faults rather than against assertions about faults.

var damaged = new InjectedStreamSource(
    new SyntheticStreamSource(new ScenarioDefinition()),
    seed: 1,
    sampleInjectors: new[] { new ByteShiftInjector(byteShift: 8) });

Scenario inputs — origin, spacing, entity count, update rate — are parameters with neutral defaults. Real values belong to whoever is consuming the library, in their own configuration.


Command line

argus replay capture.jsonl --format csv --out findings.csv

Replays a JSON Lines capture and writes self-describing findings. Exit code 1 when anything is flagged, so it drops into a pipeline.


Building

scripts/pack-local        # fills ./artifacts/local-feed
dotnet test Argus.sln

The order matters. samples/ and tests/Argus.Package.Tests consume the built .nupkg files rather than the projects, so a type accidentally left internal or a dependency that leaked into the nuspec fails here rather than in a consumer's build three months from now. scripts/build does the whole sequence including the hygiene check.


Documentation

docs/corruption-taxonomy.md What each fault looks like on the wire. Written for the team producing the stream.
docs/detector-catalogue.md Flag → meaning → method → false-positive notes.
docs/interface-contract.md What crosses the fence, and what never does.
docs/threading.md The concurrency contract, stated rather than inferred.
docs/adr/0001-core-emits-diagnostics-not-colors.md Why the core returns findings and not a colour.

Status

Early. The contracts, the pipeline, the package plumbing and one reference detector per category are in place; most of the catalogue is declared and not yet implemented. Stubs are visible rather than absent — set MonitorOptions.IncludeUnimplementedDetectors and they appear in every report as NotEvaluable, so it is always possible to see what is not being checked.

docs/detector-catalogue.md marks each entry implemented or stub.

Licence

Apache-2.0. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on BlackBeard.Argus.Core:

Package Downloads
BlackBeard.Argus.Graphics

Presentation for Argus stream diagnostics: severity-ordered colours, debug subtitles, and a compatibility facade for callers migrating from a colour-returning API. Depends on Microsoft.Maui.Graphics only.

BlackBeard.Argus.Testing

A corruption-injection harness for Argus. Generates synthetic entity streams and deliberately damages them the way a real wire format does — byte order, field offsets, scale, units, loss, reordering — so detectors can be tested against faults rather than against assertions about faults.

BlackBeard.Argus.Controls

Portable presentation state for Argus stream diagnostics: per-entity view-models, groupTag+id uniqueness, cumulative per-flag counts, and colour resolution. No UI framework dependency -- pair with BlackBeard.Argus.Controls.Maui for an actual control.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.1 173 8/31/2026
0.1.0 165 8/31/2026