Eternet.Agents.Control.Cli 2.0.28

Prefix Reserved
dotnet tool install --global Eternet.Agents.Control.Cli --version 2.0.28
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Eternet.Agents.Control.Cli --version 2.0.28
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Eternet.Agents.Control.Cli&version=2.0.28
                    
nuke :add-package Eternet.Agents.Control.Cli --version 2.0.28
                    

Eternet.Agents.Control.Cli

Eternet.Agents.Control.Cli installs the eac command, a deterministic local harness for Eternet repositories. It gives humans and agents a versioned way to discover capabilities, load implementation guidance, collect fresh diagnostics, plan remediation, apply bounded fixes, inspect mediator pipelines, call internal services, manage plugins, and verify work.

The CLI is intentionally discovery-first. Agents should not load every artifact into context. They should ask EAC for the current surface, page into the data they need, and reuse persisted run IDs instead of recomputing evidence.

Install

dotnet tool install --global Eternet.Agents.Control.Cli

Install or update a pinned version:

dotnet tool install --global Eternet.Agents.Control.Cli --version <version>
dotnet tool update --global Eternet.Agents.Control.Cli --version <version>
eac --version

When dogfooding unreleased changes from this repository, build Release and prefer the repo-local CLI command so the captured evidence matches current source instead of a potentially older global tool install:

dotnet run --project src\Eternet.Agents.Control.Cli\Eternet.Agents.Control.Cli.csproj -c Release --no-build -- --version
dotnet run --project src\Eternet.Agents.Control.Cli\Eternet.Agents.Control.Cli.csproj -c Release --no-build -- capabilities list --format json

Use the repo-local command as the default fallback while the global tool is stale or the global tool store is locked. The repo-local DLL remains a valid lower-level fallback when you specifically need to invoke the built output directly.

For local dogfood from this checkout, pack and install a timestamped tool build:

$version = "2.0.0-local.$(Get-Date -Format 'yyyyMMdd.HHmmss')"
dotnet pack src\Eternet.Agents.Control.Cli\Eternet.Agents.Control.Cli.csproj -c Release -o artifacts\nupkg /p:Version=$version /p:PackageVersion=$version
dotnet tool update --global Eternet.Agents.Control.Cli --add-source artifacts\nupkg --version $version --ignore-failed-sources
eac --version

Do not add --no-build when packing a new local tool version. A stale Release build can keep the previous AssemblyInformationalVersion, which makes eac --version look older even when the NuGet package version changed.

Package Source Mapping For Local Tool Packages

If local dogfood uses unpublished packages and NuGet.Config enables package source mapping, do not rely on --add-source alone. Use a temporary config that maps the EAC package family to the local feed and leaves nuget.org as the fallback for transitive dependencies. dotnet tool rejects combining --add-source with package source mapping, so the temporary config must carry the local feed entry by itself.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="local-eac" value="D:\src\Chat\.eac-local-feed" />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <packageSource key="local-eac">
      <package pattern="Eternet.Agents.Control.Cli" />
      <package pattern="Eternet.Agents.Control.*" />
    </packageSource>
    <packageSource key="nuget.org">
      <package pattern="*" />
    </packageSource>
  </packageSourceMapping>
</configuration>

Then point the tool install or update at that config instead of editing the repo-owned NuGet.Config:

dotnet tool update --global Eternet.Agents.Control.Cli `
  --configfile D:\temp\eac-tool.NuGet.Config `
  --version $version `
  --ignore-failed-sources

Use --tool-path <temp-dir> for disposable local smoke when you want the same package-resolution proof without mutating the real global tool store.

Locked Global Tool Store

dotnet tool update --global can fail if another shell, editor, or long-running process still has eac loaded from the global tool store. A foreground eac plan run host can hold that lock until the command exits. When that happens:

  1. Close processes that are still running eac or holding the tool files open.
  2. Retry the same dotnet tool update --global ... command once.
  3. If the machine still blocks the global store, keep verification on the current checkout with the repo-local CLI command until the store lock is cleared.
dotnet run --project src\Eternet.Agents.Control.Cli\Eternet.Agents.Control.Cli.csproj -c Release --no-build -- --version
dotnet run --project src\Eternet.Agents.Control.Cli\Eternet.Agents.Control.Cli.csproj -c Release --no-build -- capabilities list --format json

If dotnet run --project ... --no-build -- is not available, direct DLL verification is the lower-level fallback. Both paths keep rollout validation on the current source tree instead of waiting for a workstation-specific tool-store issue.

Architecture

flowchart LR
    User["Human or agent"] --> CLI["eac CLI"]
    CLI --> Discovery["Capabilities and guidance"]
    CLI --> Evidence["Diagnostics and verification"]
    CLI --> Planning["Remediation, cleanup, plan folders"]
    CLI --> Domain["Mediator, templates, legacy DB, services"]
    CLI --> Plugins["Plugin runtime"]

    Discovery --> Core["Eternet.Agents.Control.Core"]
    Evidence --> Core
    Planning --> Core
    Domain --> Core
    Plugins --> Core

    Core --> Workspace["Target workspace"]
    Core --> Artifacts[".eac/artifacts"]
    Core --> Analyzers["Transient analyzers"]
    Core --> ServiceCatalog["Internal HTTP services"]
    Core --> PluginStores["Repo/global plugin stores"]

Core owns orchestration, safety, artifact persistence, transient analyzer injection, plugin loading, and stable JSON contracts. Plugins own optional diagnostics, analyzer assemblies, code fixes, transformers, and domain migrations. The plugin migration backlog is tracked in docs/PLUGINS_TODO.md.

Progressive Disclosure

Use broad discovery commands first, search before loading authored guidance or wide plugin datasets, then narrow requests with IDs, run IDs, pages, and detail flags. Core commands reuse the common disclosure vocabulary: --detail summary for counts and next-step hints, --detail page --skip <n> --take <n> for bounded rows or sections, and --detail full for the richest projection of the current bounded page. full never means "dump every matching item inline." Queryable plugin commands use the dataset engine with --dataset, --select, --filter, --orderby, --skip, and --top; plugin authors should prefer that dataset contract for heavy row-oriented outputs instead of returning large nested payloads.

Choose the contract that matches the shape of the output:

Contract Use when Query / paging vocabulary Default and follow-up behavior
Disclosure The command returns one nested object or mixed graph and callers need summary/page/full projections. --detail summary|page|full, --skip, --take Keep the default compact; use --detail full only when the current bounded page needs the richest projection.
Dataset The command returns row-oriented inventory, findings, logs, events, or other tabular results that benefit from projection, filtering, ordering, paging, and persisted reuse. --dataset, --select, --filter, --orderby, --skip, --top, --persist-result, --result-id Keep the default dataset preview bounded; let callers ask for more rows or a persisted result explicitly.
List The command already returns a small flat list and does not need nested disclosure or dataset semantics. --skip, --take Keep list paging separate from dataset --top.
Guidance The command returns authored knowledge, not operational data. guidance search, guidance toc, guidance show --detail summary|page|full, --search, --skip, --take Search first, then load one bounded page of matching sections. Legacy --full remains a compatibility alias for the same bounded --detail full behavior.

Every partial response should surface enough follow-up data to continue safely instead of forcing the caller to guess: pageInfo for counts/cursors, budgetInfo and partialInfo for truncation reason, next/previous/search commands when available, and artifact references when the full payload is only safe out of band.

Default response budgets come from ADR 0002 and stay physically enforced even after semantic normalization:

Response budget Default page Full-page ceiling Hard max
Serialized response chars 30,000 60,000 120,000
Serialized response UTF-8 bytes 64 KiB 128 KiB 256 KiB

If a command misses semantic paging, the final writer guardrail returns a compact fallback envelope rather than leaking the raw oversized payload. That fallback keeps the command name, observed size, and any continuation, search, or artifact hints needed to fetch more safely.

Guidance Section Model

Guidance packs now publish stable authored sections instead of one synthetic full blob. Start with guidance search --query <text> when you know the concept but not the pack id, then use guidance toc --id <pack> to inspect section ids, titles, and tags before loading content. guidance show --id <pack> returns the pack's compact/default sections, guidance show --sections <id> and guidance show --tags <tag> load authored slices intentionally, and guidance show --detail full returns all matching sections for the current bounded page. Legacy guidance show --full is still accepted, but it maps to the same bounded full-detail page behavior and does not bypass budgets.

Release-oriented packs can expose larger non-compact sections, such as rollout guidance, without forcing those sections into the compact default output that agents load by default.

Consumer Migration Notes

When updating existing scripts, docs, or agent prompts for the economy model:

  • Treat compact output as the default contract. If a command used to return the full graph by default, request --detail full explicitly or move to --detail page when a bounded slice is enough.
  • For guidance, switch from loading whole packs up front to guidance search, then guidance toc, then guidance show --detail page ... or guidance show --detail full ... for the current bounded page.
  • For queryable plugin output, stop parsing plugin-specific payload.resultJson blobs or legacy paging flags and use the host-owned dataset query and cache options instead.
flowchart TD
    Start["Start task"] --> Cap["eac capabilities --format json"]
    Cap --> CapList["capabilities list"]
    CapList --> CapShow["capabilities show --id <id>"]
    Cap --> GuidanceList["guidance list"]
    GuidanceList --> Families["guidance families"]
    Families --> Family["guidance family --id <family>"]
    GuidanceList --> GuidanceSearch["guidance search --query <text>"]
    GuidanceSearch --> Toc["guidance toc --id <pack>"]
    Toc --> Sections["guidance show --id <pack> --detail page"]
    Sections --> Work["Run focused evidence command"]

Diagnostics use the same model:

sequenceDiagram
    participant A as Agent
    participant E as eac
    participant W as Workspace
    participant F as .eac artifacts

    A->>E: diagnose all --workspace <repo> --format json
    E->>W: inject transient analyzers and build
    E->>F: persist result.json and logs
    E-->>A: compact manifest with runId and grouped counts
    A->>E: diagnose list --from-run <runId> --source eac --diagnostic <id>
    E-->>A: one page of findings
    A->>E: diagnose show --from-run <runId> --item eac:0
    E-->>A: one focused diagnostic with properties

Capability Map

flowchart TB
    EAC["eac"]
    EAC --> Discover["Discovery<br/>capabilities, guidance"]
    EAC --> Diagnose["Evidence<br/>diagnose, tooling, verify"]
    EAC --> Remediate["Remediation<br/>status, waves, code fixes"]
    EAC --> Cleanup["Cleanup impact<br/>inventory, reachability, cleanup"]
    EAC --> Mediator["Mediator<br/>inventory, inspect, graph, validate, compare"]
    EAC --> Plans["Plan folders<br/>inspect, scaffold, runbook, workflow, guard, run"]
    EAC --> Plugins["Plugins<br/>inspect, install, list, uninstall"]
    EAC --> Services["Services<br/>auth, catalog, invoke"]
    EAC --> Templates["Templates<br/>list, show, install, update, create"]
    EAC --> Legacy["Legacy DB<br/>snapshots and testing assets"]
    EAC --> AI["Read-only AI<br/>reason"]

Command Surface

Area Commands Purpose
Discovery capabilities, capabilities list, capabilities show Discover the installed EAC command and guidance contract.
Guidance guidance list, guidance search, guidance show, guidance toc, guidance suggest, guidance families, guidance family Search and load versioned guidance progressively instead of relying on stale prompt memory.
Diagnostics diagnose, diagnose all, diagnose ingest, diagnose list, diagnose show Produce or inspect normalized analyzer evidence.
Tooling tooling inspect, tooling update Check, update, and bootstrap diagnostic package declarations that affect evidence completeness.
Remediation remediation plan, remediation status, remediation waves, remediation code-fixes, remediation apply-codefix Convert stored diagnostics into recipes, waves, and bounded deterministic fixes.
Verification verify Re-check current worktree evidence and optionally run build/test commands.
Cleanup inventory collect, reachability analyze, cleanup plan, cleanup explain, cleanup diff, cleanup verify Analyze deletion/trim impact from persisted inventory, explicit specs, and git diff evidence.
Mediator mediator inventory, mediator inspect, mediator graph, mediator validate, mediator compare Inspect mediator pipeline facts, quality signals, graphs, and persisted snapshots.
Review review pr Create artifact-first PR review contracts by dispatching the Core review command and emitting contract/lineage/runtime artifacts.
Plan folders plan inspect, plan scaffold, plan runbook, plan workflow, plan guard, plan run Standardize repo-local plan execution and guard checks.
Plugins plugins inspect, plugins install, plugins list, plugins uninstall Discover, install, and run EAC plugin packages.
Templates templates list, templates show, templates install, templates update, templates create Discover and instantiate allowlisted Eternet .NET templates.
Services services list, services show, services operations, services operation, services schemas, services operation-schema, services health, services invoke Discover and call allowlisted internal HTTP services through OpenAPI metadata.
Auth auth login, auth status, auth logout, auth token list, auth token revoke, auth approval request, auth approval status, auth approval cancel Store and manage server tokens plus supervisor approval lifecycle used by service calls.
Legacy DB legacy-db snapshots status, versions, show, download, create; legacy-db testing scaffold, refresh, inspect Manage legacy DB metadata snapshots and repo-local testing assets.
AI ai reason Ask Copilot or Codex for read-only reasoning. Not a source of deterministic evidence.

Review Contracts

review pr is artifact-first by default and dispatches the Core ExecutePullRequestReviewCommand boundary. The CLI accepts a full Core request/configuration file through --config, overlays explicit flags, then emits a contract JSON plus companion markdown/lineage/runtime metadata artifacts when --emit is provided.

eac review pr --workspace <repo> --pull-request-url https://github.com/org/repo/pull/42 --backend copilot --model gpt-5.4 --publish-canonical-comment false --publish-inline-comments false --emit .eac/review/review-pr-contract.json --format json

For local dogfood, --workspace can infer owner/repo from the GitHub origin remote, so the PR number is enough:

eac review pr 42 --workspace <repo> --emit .eac/review/pr-42 --format json

For remote-only artifact runs, a full pull request URL can be supplied without a workspace:

eac review pr https://github.com/org/repo/pull/42 --emit .eac/review/pr-42 --format json

Use repeatable --step-override values to control individual lanes:

eac review pr --config review-config.json --step-override concurrency:selectionMode=run,agent=codex,model=gpt-5.4,timeoutSeconds=900 --step-override relationalFramework:selectionMode=skip,enabled=false

Safe dogfood runs should keep publication disabled with --publish-canonical-comment false and --publish-inline-comments false. --canonical-publication-mode accepts per-execution, rolling, or per-revision; disabling publication is controlled by the publication flags, not by a none mode.

Discovery And Guidance

Start every agent workflow by discovering the installed contract:

eac capabilities --format json
eac capabilities list --format json
eac guidance list --format json
eac guidance search --query mediator --format json
eac guidance families --format json

Then load only the relevant detail:

eac capabilities show --id remediation-waves --format json
eac guidance toc --id mediator --format json
eac guidance show --id mediator --detail page --take 1 --format text
eac guidance show --id mediator --sections quick-start,decision-tree --detail full --format text
eac guidance suggest --diagnostic EAR001 --format json

Current guidance domains include agent workflow, cleanup impact, templates, plan folders, review dogfood hardening, services, legacy DB testing, mediator implementation, mediator testing, mediator contracts, relational CRUD, naming, REST endpoints, legacy entities, Firebird, Blazor testing, and EternetDataGrid.

Profile-Aware Capability Listing

Capability discovery supports profile-aware authorization and local-safety projection:

# Allowed capabilities only (default projection)
eac capabilities list --format json

# Include denied capabilities with denial reason tokens
eac capabilities list --include-denied --format json

# Project current-user capability profile summary
eac capabilities profile --format json

When denied capabilities are included, each item can project denialReason values such as authzDenied, localSafetyDenied, authMissing, authExpired, and authUnavailable so automation can branch without parsing prose. When canRequestSupervisorApproval is true, denial messages include request and retry guidance.

Plugin Capabilities

Plugin capabilities are generated from validated executable CLI command leaves, not from manifest tags. Every plugin command that has an OperationId or DiagnosticId generates a corresponding agent-facing capability.

Authoritative Source

Executable capabilities come exclusively from EacPluginCliCommand leaves after alias and scope resolution:

# List all host and built-in capabilities (no workspace required)
eac capabilities list --format json

# List built-in plugin capabilities only
eac capabilities list --plugin built-in --format json

# List capabilities from a specific plugin by alias (requires workspace for repo/global plugins)
eac capabilities list --plugin sf --workspace <repo> --format json

# Show detailed capability information (workspace required for plugin capabilities)
eac capabilities show --id plugin-sf-inventory --workspace <repo> --format json

Important: Plugin capabilities are inaccessible without --workspace context. Use --workspace <repo> to resolve repo-scoped or global plugin capabilities.

Manifest Capabilities vs Executable Commands

Manifest.Capabilities is non-authoritative for agent command discovery. Manifest tags are catalog metadata only:

  • Manifest.Capabilities: Freeform package tags for discovery, review, and human-facing categorization (not validated).
  • Cli.Commands leaves: Executable command paths with validated intent, options, output contract, and apply support (authoritative).

Agents must use capabilities list and capabilities show to discover executable plugin capabilities, not parse manifest tags. See ADR 0003 for details.

Structured Capability Fields

Starting with contract version 2.1, CommandCapability exposes typed fields for agent-driven filtering:

{
  "id": "plugin-sf-inventory",
  "name": "sf inventory",
  "description": "Query Service Fabric nodes and services",
  "agentDefault": false,
  "producesFreshEvidence": true,
  "stableJsonOutput": true,
  "workspaceMode": "optional",
  "supportsApply": false,
  "hasQueryableOutput": true,
  "defaultDatasetId": "live-nodes",
  "operationId": "service-fabric-inventory",
  "diagnosticId": null,
  "pluginScope": "repo",
  "pluginPackageId": "EAC.Plugin.Extension.ServiceFabric",
  "pluginVersion": "0.1.0",
  "aliasSource": "eac sf",
  "pluginPermissions": ["github:repo"],
  "relatedGuidanceIds": ["sf-cluster-health", "sf-node-remediation"],
  "constraints": ["Requires Service Fabric cluster connection"],
  "samples": [...]
}

These fields enable agents to filter by workspace mode, apply support, queryable output, operation/diagnostic IDs, plugin scope, and permissions without parsing prose description.

Backward Compatibility: Existing consumers that ignore structured fields continue to work. Prose fields (Description, Constraints, Samples) remain for human readability and backward compatibility.

Additive Capability Enrichment

Optional plugin metadata (EacPluginCliCapability) enriches generated capabilities without duplicating the executable contract:

  • Does NOT override: command path, intent, options, output contracts, apply support.
  • Does enrich: agent defaults, fresh-evidence signals, category tags, guidance links, safety notes, example invocations.

See ADR 0002 and ADR 0004 for details.

Diagnostics

diagnose generates fresh evidence by building the workspace with transient analyzer injection. The stdout JSON is a compact manifest; the full run is persisted under .eac/artifacts/diagnose/<run-id>/.

eac diagnose --workspace <repo> --format json
eac diagnose all --workspace <repo> --target src/App.slnx --format json
eac diagnose all --workspace <repo> --diff HEAD --format json
eac diagnose --workspace <repo> --changed-files src/Foo.cs,src/Bar.cs --format json

Use stored-run paging instead of loading result.json into context:

eac diagnose list --workspace <repo> --from-run <run-id> --source eac --diagnostic EANC001 --skip 0 --take 50 --format json
eac diagnose show --workspace <repo> --from-run <run-id> --item eac:0 --format json
eac diagnose list --workspace <repo> --from-run <run-id> --source external --diagnostic CS8602 --take 25 --format json

diagnose ingest exists for compatibility and debugging existing SARIF. Use fresh diagnose or verify for agent verification.

Tooling Health

Some diagnostics depend on Eternet runtime and generator/analyzer package declarations in the target repo.

eac tooling inspect --workspace <repo> --profile mediator --format json
eac tooling update --workspace <repo> --profile mediator --format json
eac tooling update --workspace <repo> --profile mediator --apply --format json

Run tooling update without --apply first. It can update stale versions and add missing package declarations. After applying package updates, run fresh diagnostics again.

Remediation

Remediation is run-ID based. First collect evidence, then plan/status/waves from that same run.

flowchart LR
    Diagnose["diagnose all"] --> RunId["runId"]
    RunId --> Status["remediation status"]
    RunId --> Plan["remediation plan --diagnostic <id>"]
    RunId --> Waves["remediation waves --emit-plan"]
    RunId --> DryRun["remediation apply-codefix"]
    DryRun --> Apply["remediation apply-codefix --apply"]
    Apply --> Verify["verify"]

Common commands:

eac remediation status --workspace <repo> --from-run <run-id> --format json
eac remediation plan --workspace <repo> --diagnostic EAR001 --from-run <run-id> --format json
eac remediation waves --workspace <repo> --from-run <run-id> --emit-plan .eac/remediation/waves.md --format json
eac remediation code-fixes --format json
eac remediation apply-codefix --workspace <repo> --from-run <run-id> --diagnostic EM018 --format json
eac remediation apply-codefix --workspace <repo> --from-run <run-id> --diagnostic EM018 --apply --format json

Do not run broad dotnet format analyzers commands by hand for EAC remediation. EAC owns explicit target files, batch sizes, safety metadata, dry-run/apply separation, and postflight expectations.

Analyzer Plugin Stack

The first-party analyzer rollout is package-based:

  • EAC.Plugin.AnalyzerCatalog is the built-in catalog plugin boundary.
  • The family packages own the analyzer DLLs and any package-owned codeFixMetadata in eac-plugin.json.
  • remediation code-fixes reports sourcePackage from the owning family package manifest, not from legacy Eternet.Analyzers.

Current built-in family packages are:

  • EAC.Plugin.Naming
  • EAC.Plugin.FeatureFolder
  • EAC.Plugin.Localization
  • EAC.Plugin.Contracts
  • EAC.Plugin.OData
  • EAC.Plugin.Mediator
  • EAC.Plugin.Mediator

When dogfooding unpublished analyzer packages, pack them to a local feed, set EAC_ANALYZER_PACKAGE_SOURCES, and point restore at a config that maps EAC.Plugin.AnalyzerCatalog* to that feed when NuGet.Config uses package source mapping. This keeps diagnose and code-fix execution on the normal NuGet/MSBuild path instead of a custom loader.

To add a future analyzer package, ship the analyzer DLLs and optional codeFixMetadata in the owning family package, update the built-in catalog plugin only if the package should load by default, and extend the dogfood/test feed recipe so the new package can be restored before publication.

Verification

eac verify --workspace <repo> --target <change-name> --format json
eac verify --workspace <repo> --target <change-name> --build-target src/App.slnx --format json
eac verify --workspace <repo> --target <change-name> --tests "dotnet test tests/App.Tests/App.Tests.csproj -c Release --no-restore" --format json

Analyzer/build evidence is the default verification path. Tests are opt-in because they can be expensive or domain-specific.

Cleanup Impact Analysis

Cleanup work uses persisted inventory plus an explicit cleanup spec.

flowchart TD
    Inventory["inventory collect"] --> Reachability["reachability analyze --from-inventory"]
    Reachability --> Explain["cleanup explain"]
    Reachability --> Plan["cleanup plan"]
    Plan --> Edits["Manual or agent cleanup edits"]
    Edits --> Diff["cleanup diff --baseline"]
    Diff --> Verify["cleanup verify"]

Commands:

eac inventory collect --workspace <repo> --target src/App.slnx --profile source,blazor,aspnet,mediator --include src,tests --exclude docs --format json
eac reachability analyze --workspace <repo> --from-inventory <run-id> --spec cleanup-spec.json --format json
eac cleanup explain --workspace <repo> --from-run <run-id> --file src/Legacy/Foo.cs --format json
eac cleanup plan --workspace <repo> --from-run <run-id> --detail summary --format json
eac cleanup plan --workspace <repo> --from-run <run-id> --detail full --emit-plan .eac/cleanup/waves.md --format json
eac cleanup diff --workspace <repo> --baseline main --head HEAD --format json
eac cleanup verify --workspace <repo> --spec cleanup-spec.json --from-run <run-id> --include src,tests --exclude docs --format json

Use the same include/exclude scope for inventory and verification when docs, plans, samples, or archived code are not part of the product surface. Use cleanup diff after edits to quantify added, modified, and deleted files by cleanup bucket, deleted .cs test files by tests/<project>, and removed [Fact]/[Theory] attributes. Treat uncertain dynamic usage as blocked, not deletable.

Mediator Inspection

Mediator commands expose pipeline inventory without forcing the agent to infer everything from source text.

eac mediator inventory --workspace <repo> --tier catalog --page-size 5 --format json
eac mediator inventory --workspace <repo> --pipeline EnrichIssueOnDemand --tier outline --format json
eac mediator inventory --workspace <repo> --pipeline ReasonWithAi --tier full --format json
eac mediator inspect --workspace <repo> --symbol EnrichIssueOnDemand --detail summary --format json
eac mediator inspect --workspace <repo> --file src/App/Features/Orders/ExecuteOrder.cs --detail full --format json
eac mediator graph --workspace <repo> --symbol ReasonWithAi --graph-format mermaid --format json
eac mediator validate --workspace <repo> --pipeline ReasonWithAi --format json
eac mediator compare --workspace <repo> --baseline baseline.json --current current.json --format json

Inventory output is tiered:

  • catalog: one row per pipeline, capped for discovery.
  • outline: ordered steps and key risk signals.
  • full: step contracts, graph, diagnostics, recipes, and quality findings.

Large workspaces should use --tier, --page, --page-size, --limit, --pipeline, --diff, --changed-files, or --from-run to keep output bounded.

<details> <summary>Example: catalog page from this repo</summary>

Command:

eac mediator inventory --workspace D:/src/Chat/Eternet.Agents.Control --tier catalog --page-size 5 --format json

Trimmed output:

{
  "version": "2.0",
  "tier": "catalog",
  "pageInfo": {
    "page": 1,
    "pageSize": 5,
    "totalCount": 229,
    "hasNextPage": true,
    "cursor": "ListAuthTokens"
  },
  "catalog": [
    {
      "name": "ReasonWithAi",
      "kind": "execute",
      "stepCount": 1,
      "branchCount": 0,
      "isStateful": false,
      "hasRetry": false,
      "file": "src/Eternet.Agents.Control.Cli/Commands/Ai/ReasonWithAi/ReasonWithAi.cs",
      "line": 28,
      "diagnosticCount": 2
    }
  ]
}

</details>

<details> <summary>Example: outline for a Web enrichment pipeline</summary>

Command:

eac mediator inventory --workspace D:/src/Chat/Eternet.Agents.Control --pipeline EnrichIssueOnDemand --tier outline --format json

Trimmed output:

{
  "version": "2.0",
  "tier": "outline",
  "pageInfo": {
    "totalCount": 1,
    "hasNextPage": false
  },
  "outlines": [
    {
      "name": "EnrichIssueOnDemand",
      "kind": "execute",
      "file": "src/Eternet.Agents.Control.Web/Features/Enrichment/EnrichIssue/EnrichIssueOnDemand.cs",
      "requestType": "EnrichIssueOnDemand.Request",
      "responseType": "EnrichIssueOnDemand.Response",
      "steps": [
        { "order": 1, "name": "GetIssueWithRepositoryAsync", "isAsync": true },
        { "order": 7, "name": "BuildEnrichmentInventoryAsync", "hasEfWrite": true, "isAsync": true },
        { "order": 15, "name": "PersistEnrichmentResultAsync", "hasEfWrite": true, "isAsync": true },
        { "order": 18, "name": "FinalizeEnrichIssueResult", "isAsync": false }
      ],
      "saveChangesCount": 1,
      "writeUnitCount": 5,
      "isStateful": false,
      "hasRetry": false,
      "diagnosticIds": ["EANM011", "EAR001"]
    }
  ]
}

</details>

<details> <summary>Example: graph output for a small CLI pipeline</summary>

Command:

eac mediator graph --workspace D:/src/Chat/Eternet.Agents.Control --symbol ReasonWithAi --graph-format mermaid --format json

Trimmed output:

{
  "graphFormat": "mermaid",
  "graph": {
    "summary": {
      "pipelineCount": 1,
      "nodeCount": 2,
      "edgeCount": 1
    }
  },
  "source": {
    "primary": "sourceScan"
  },
  "text": "flowchart TD\n  pipeline_ReasonWithAi[\"ReasonWithAi\"]\n  step_ExecuteReasoningAsync[\"ExecuteReasoningAsync\"]\n  pipeline_ReasonWithAi -->|starts-with| step_ExecuteReasoningAsync"
}

Rendered:

flowchart TD
  pipeline_ReasonWithAi["ReasonWithAi"]
  step_ExecuteReasoningAsync["ExecuteReasoningAsync"]
  pipeline_ReasonWithAi -->|starts-with| step_ExecuteReasoningAsync

</details>

Plan Folders

EAC can scaffold and inspect repo-local plan folders, identify the next wave, generate runbooks, run configured guards, and optionally run the implementer pass. In this repository, those plan-folder operations are owned by the built-in EAC.Plugin.Plans plugin. The CLI host keeps PlanCommandModule only as a compatibility adapter so the public eac plan command names, JSON shape, and streamed-run behavior stay stable while plan ownership remains plugin-backed. Current dogfood still shows that the compatibility adapter does not expose the plugin dataset query flags on the root eac plan surface, so --dataset, --select, --filter, --orderby, --skip, --top, and --count remain follow-up work even though the underlying plan plugin metadata advertises queryable output. Until that host parity lands, treat root eac plan automation as bounded default output plus explicit runbook/workflow follow-ups; do not script dataset query flags against the compatibility adapter yet.

eac plan scaffold --workspace <repo> --name billing-migration --title "Billing Migration" --format json
eac plan scaffold --workspace <repo> --name billing-migration --title "Billing Migration" --apply --format json
eac plan inspect --workspace <repo> --plan-folder plans/billing-migration --format json
eac plan runbook --workspace <repo> --plan-folder plans/billing-migration --format json
eac plan workflow --workspace <repo> --plan-folder plans/billing-migration --format json
eac plan guard --workspace <repo> --plan-folder plans/billing-migration --format json
eac plan run --workspace <repo> --plan-folder plans/billing-migration --print-only --format json
eac plan run --workspace <repo> --plan-folder plans/billing-migration --format json

Use plan runbook when another runner should execute the wave. Backend, model, and reasoning normally resolve from local-wave-stack.settings.json; --backend, --model, and --reasoning-effort are temporary overrides and should be recorded in the active wave when used. Run plan run as a foreground, blocking command; do not start it in the background and poll PIDs, logs, or activity artifacts. plan run owns backend waiting, mirrors child-agent output to stderr, and preserves the final structured result on stdout. Use plan guard to validate plan rules without running an agent CLI.

Dogfood Evidence

Plan folders can also carry replayable evidence summaries for closeout gates:

eac plan evidence extract-rollout --workspace <repo> --plan-folder plans/<plan> --rollout-log <jsonl> --source-id CHAT-1381 --output reports/chat-1381-summary.json --format json
eac plan evidence import-github --workspace <repo> --plan-folder plans/<plan> --fixture reports/github-fixture.json --output reports/github-api-1381-summary.json --format json

extract-rollout parses Codex JSONL structurally and writes bounded summaries so image/base64 payloads do not become the review surface. import-github imports a replayable fixture with stable source ids. plan evaluate checks reports/dogfood-failure-catalog.json against reports/dogfood-evidence-sources.json and fails closed when referenced sources are missing or stale.

Plugins

Plugins extend EAC without forcing every optional diagnostic or migration into the CLI host.

The boundary is intentionally strict. Core owns mandatory EAC host behavior: templates, guidance precedence, stable contracts, safety gates, artifact persistence, plugin runtime loading, and the rules for authoring and controlling Eternet pipelines. Plugins own optional diagnostics, repository-specific migration helpers, transient package migrations, custom transformers, and first-party command families that intentionally stay outside Core implementation, such as the built-in EAC.Plugin.Plans plan-folder surface.

Built-in plugins are first-party plugins admitted by the current CLI build. They can be carried as normal package or project references, but they still implement IEacPlugin and stay outside Eternet.Agents.Control.Core. Built-in does not mean "merge into Core"; it means "available without repo/global install because this CLI version deliberately ships it." Transient or environment-specific plugins such as the catalog EAC.Plugin.Extension.Assertions, EAC.Plugin.Extension.LegacyDB, and EAC.Plugin.Extension.ServiceFabric packages stay opt-in by default and should not become Core implementation.

Reusable plugin work can start in the sibling Eternet.Agents.Control.Plugins repository. If it becomes first-party and needs closer maintenance with EAC, either pin its package as a built-in CLI dependency or move the whole plugin project into this repository beside Core. In both cases the plugin boundary remains the same so agents and developers can keep creating plugins without risking Core behavior.

flowchart LR
    BuiltIn["Built-in CLI references"] --> Runtime["Plugin runtime"]
    Catalog["Plugin catalog service"] --> Install["eac plugins install"]
    Local["Local dll/nupkg/directory/url"] --> Inspect["eac plugins inspect"]
    Inspect --> Install
    Install --> Store["repo/global plugin store"]
    Store --> Runtime
    Runtime --> Diagnose["diagnose loads plugin analyzers and providers"]
    Runtime --> CodeFix["remediation apply-codefix dispatches plugin providers"]

What plugins can contribute today:

  • Roslyn analyzer assemblies discovered from standard NuGet analyzer layout.
  • IEacDiagnosticProvider diagnostics for non-Roslyn or source-only scans.
  • Roslyn-dotnet-format code-fix metadata through an IEacPlugin adapter.
  • IEacTransformerProvider migrations for operations that do not fit normal Roslyn code fixes.
  • Manifest metadata: capabilities, permissions, package ID, minimum EAC version, and plugin API version.

Commands:

eac plugins inspect --path <dll-or-nupkg-or-directory-or-url> --format json
eac plugins install --package EAC.Plugin.Extension.Assertions --workspace <repo> --scope repo --format json
eac plugins install --package <package-id> --version <version> --nuget --workspace <repo> --scope repo --format json
eac plugins install --path <local-or-http-nupkg> --workspace <repo> --scope repo --format json
eac plugins list --workspace <repo> --format json
eac plugins list --scope built-in --format json
eac plugins list --workspace <repo> --scope all --format json
eac plugins uninstall --package <package-id> --workspace <repo> --scope repo --format json

Repo-scoped plugins live under <workspace>/.eac/plugins. Global plugins live in the user plugin store or EAC_PLUGIN_GLOBAL_STORE when set. Built-in plugins are read-only first-party CLI references carried by the CLI package itself. They still implement IEacPlugin and are resolved through the same manifest/capability contract as external plugins, but they do not require repo or global installation.

For local development, first-party built-ins that live in this repository are referenced as sibling projects when the CLI is restored with EacIncludeBuiltInPluginPackageReferences=true. Opt-in catalog plugins that are deliberately kept outside this repository, such as EAC.Plugin.Extension.Assertions, EAC.Plugin.Extension.LegacyDB, and EAC.Plugin.Extension.ServiceFabric, come from the private catalog or local package feeds. Because this repo uses NuGet package source mapping, local dogfooding for external plugin packages needs a temporary NuGet config that maps the external package ID family to that feed.

EAC.Plugin.Extension.ServiceFabric intentionally stays in that external catalog lane for now. It is Eternet-specific operational tooling, depends on environment-specific endpoints and the read-only svc-eac-sfdiag identity, and should keep its own rollout cadence instead of becoming a built-in CLI dependency before deploy/restart/ upgrade workflows are proven.

The normal install path is global because the Service Fabric profile is machine/operator configuration, not repository state:

eac plugins install --package EAC.Plugin.Extension.ServiceFabric --scope global --format json

After install, sf doctor diagnoses host/config/node prerequisites without requiring --workspace. sf bootstrap --apply stays bounded to local global EAC artifacts under service-fabric/ in EAC_CONFIG_HOME or %USERPROFILE%/.eac, and never installs software or mutates remote nodes. Supplying --workspace <repo> only enables source-repo enrichment.

Built-In And Opt-In Inventory

The current built-in plugin stack shipped by the CLI includes analyzer catalog, built-in recipes, contracts, CRUD relational, legacy mediator-generator compatibility, feature-folder, localization, mediator, naming, OData, plan folders, review/source diagnostics, and validation plugins. A local dogfood build may also carry a pinned assertion-migration package as built-in; that is still plugin admission, not Core ownership.

The sibling Eternet.Agents.Control.Plugins repository currently carries opt-in catalog packages:

  • EAC.Plugin.Extension.Assertions with alias eac assertions migrate.
  • EAC.Plugin.Extension.LegacyDB with alias eac legacy-query export.
  • EAC.Plugin.Extension.ServiceFabric with alias eac sf ....

Use eac plugins list --scope built-in --format json to inspect the built-in set in the installed CLI, and eac services operations --service plugins --format json or eac plugins install --package <package> to consume the catalog.

<details> <summary>Example: inspecting the assertion migration plugin</summary>

Command:

eac plugins inspect --path D:/src/Chat/Eternet.Agents.Control.Plugins/artifacts/nupkg/EAC.Plugin.Extension.Assertions.0.1.0.nupkg --format json

Trimmed output:

{
  "success": true,
  "plugins": [
    {
      "pluginId": "EAC.Plugin.Extension.Assertions",
      "packageId": "EAC.Plugin.Extension.Assertions",
      "displayName": "Assertion Package Migrations",
      "version": "0.1.0",
      "description": "Detects and migrates FluentAssertions package references to AwesomeAssertions.",
      "pluginApiVersion": "2.0",
      "minimumEacVersion": "2.0.17",
      "capabilities": ["EPKG002"],
      "permissions": ["readWorkspace", "writeWorkspace", "network"],
      "diagnostics": ["EPKG002"],
      "codeFixes": ["EPKG002"],
      "transformers": ["EPKG002"]
    }
  ],
  "warnings": []
}

</details>

The assertion migration plugin migrates FluentAssertions package metadata and supported C# using directives to AwesomeAssertions. Future migration candidates are tracked in docs/PLUGINS_TODO.md.

Queryable Plugin Output V2 Cutover

Queryable plugin operations now ship on the stable plugin API v2 contract.

Use the existing dataset runtime when the plugin output is naturally row-oriented:

  • inventory or catalog rows;
  • findings, events, logs, or other repeated records;
  • data that users need to page, filter, sort, or project into a small set of columns;
  • results that benefit from persisted reuse through --persist-result and --result-id.

Prefer a disclosure-style command instead when the output is one nested object or mixed graph and the caller is more likely to ask for summary, page, or full than for arbitrary select / filter queries. Keep mutation commands such as assertions migrate and sf bootstrap on bounded summary / preview output instead of flattening them into a default dataset contract.

ADR 0003 vocabulary is intentional:

  • disclosure and simple list paging use --skip / --take;
  • dataset query paging uses --skip / --top;
  • do not add --top aliases to disclosure commands or --take aliases to dataset commands.

Compact-by-default examples:

eac services show --service legacy-db --format json
eac guidance show --id plan-folders --format text
eac sf inventory --workspace <repo> --top 5 --count --format json

Full-detail or follow-up escapes:

eac services show --service legacy-db --detail full --format json
eac guidance show --id plan-folders --detail full --take 1 --format text
eac sf inventory --workspace <repo> --dataset live-nodes --select name,status --orderby "name asc" --top 25 --persist-result --format json
eac sf inventory --workspace <repo> --dataset live-nodes --result-id <persisted-result-id> --top 25 --format json

Legacy eac guidance show --id plan-folders --full --format text remains accepted for compatibility, but it resolves to the same bounded full-detail page and still emits continuation or artifact hints when more content exists than one inline response can safely carry.

The built-in EAC.Plugin.Plans metadata remains the reference implementation for dataset-backed plugin commands in source, even though the current host-owned plan root command still has a query-flag parity gap. Treat that gap as host-surface debt, not as evidence that the dataset runtime is missing.

Breaking changes for callers:

  • Stop parsing primary payload.resultJson; migrated commands now keep JSON compact by default and expose datasets, counts, findings, artifacts, render hints, and an optional bounded payload object.
  • Treat text and JSON as two renderings of the same dataset-first envelope. The default preview is bounded and the same query options drive both renderers.
  • Use host-owned query/cache options instead of plugin-specific paging flags: --dataset, --select, --filter, --orderby, --skip, --top, --count, --persist-result, and --result-id.
  • --select accepts repeated values or a comma-separated list, for example --select operationId --select groupName and --select operationId,groupName are equivalent.

Cache and refresh behavior:

  • Fresh execution is the default. Run the plugin command without --result-id to query the live/source data again.
  • Reuse is explicit. Pass --result-id <id> to query a persisted SQLite result without invoking the plugin provider again.
  • A result is persisted when the user passes --persist-result or when the plugin dataset declares cacheHint.defaultMode as persisted.
  • JSON output includes createdAtUtc, expiresAtUtc, persistedResult, reusedResult, and each dataset page's skip, top, returnedCount, totalCount, and hasMore values. Text output prints the data creation time, cache expiration when present, and a next-page hint when more rows are available.
  • Persisted query results are stored under EAC_PLUGIN_RESULTS_ROOT when set. On Windows, the default root is %LOCALAPPDATA%/EAC/plugin-results; older %USERPROFILE%/.eac/plugin-results results are still readable by id.
  • On Windows, EAC stages the SQLite native dependency in a short writable path before opening local datasets. Override that path with EAC_SQLITE_NATIVE_ROOT if an environment needs a specific location.

Dogfood closed the cutover on the stable 2.0.17 package line:

eac plugins inspect --path D:/src/Chat/Eternet.Agents.Control.Plugins/artifacts/nupkg/EAC.Plugin.Extension.ServiceFabric.0.1.0.nupkg --format json
eac plugins install --path D:/src/Chat/Eternet.Agents.Control.Plugins/artifacts/nupkg/EAC.Plugin.Extension.ServiceFabric.0.1.0.nupkg --workspace D:/src/Chat/Eternet.Agents.Control.Plugins --scope repo --format json
eac sf inventory --workspace D:/src/Chat/Eternet.Agents.Control.Plugins --format json --top 5 --count
eac sf inventory --workspace D:/src/Chat/Eternet.Agents.Control.Plugins --dataset live-nodes --select name,healthState,status --orderby "name asc" --top 2 --count --result-id <persisted-result-id> --format json

The same contract now covers the LegacyDB migration plugin:

eac plugins inspect --path D:/src/Chat/Eternet.Agents.Control.Plugins/artifacts/nupkg/EAC.Plugin.Extension.LegacyDB.0.1.0.nupkg --format json
eac legacy-query export --workspace <target-workspace> --source-workspace <source-workspace> --wave-file docs/endpoint-migration/plans/waves/billing.md --service Eternet.Billing --operation-namespace BillingApi --group Billing_Route --declared-only --emit-query-code --dataset legacy-query-endpoints --select operationName --select suggestedContractsPath --orderby "operationName asc" --top 2 --count --format json

Templates

eac templates list --format json
eac templates show --template eternet-sf-webapi --format json
eac templates install --package Eternet.ServiceFabric.WebApi.Template --format json
eac templates update --package Eternet.ServiceFabric.WebApi.Template --format json
eac templates update --package Eternet.ServiceFabric.WebApi.Template --apply --format json
eac templates create --template eternet-sf-webapi --name MyService --output D:/src/MyService --format json
eac templates create --template eternet-sf-webapi --name MyService --output D:/src/MyService --apply --format json

Create and update commands dry-run by default. Add --apply for mutation.

Services And Auth

Services are allowlisted internal HTTP APIs discovered through OpenAPI.

eac services list --format json
eac services show --service legacy-db --detail summary --format json
eac services show --service legacy-db --detail full --format json
eac services operations --service legacy-db --skip 0 --take 25 --format json
eac services operation --service legacy-db --operation ListProcedures --format json
eac services schemas --service legacy-db --detail summary --format json
eac services schemas --service legacy-db --search CloneSession --detail page --skip 0 --take 25 --format json
eac services operation-schema --service legacy-db --operation CreateCloneSession --format json
eac services health --service legacy-db --format json
eac services invoke --service legacy-db --operation ListProcedures --param page=1 --param pageSize=50 --format json
eac services invoke --service gateway-authz --operation CurrentUserBatchAuthorize --approval-id <approval-id> --format json
eac services operations --service plugins --format json
eac services operations --service gateway-authz --format json

Authenticated services use stored EAC auth tokens:

eac auth login --server http://db.eternet.cc:5080 --provider github
eac auth status --server http://db.eternet.cc:5080 --provider github --format json
eac auth token list --server http://db.eternet.cc:5080 --provider github --format json
eac auth token revoke --server http://db.eternet.cc:5080 --provider github --id <token-id> --format json
eac auth approval request --namespace Auth --route-template /Auth/Me/Authorize/Batch --operation Read --permission-key Auth.Me.AuthorizeBatch.Read --reason "temporary override" --format json
eac auth approval status --id <approval-id> --format json
eac auth approval cancel --id <approval-id> --reason "no longer needed" --format json
eac auth logout --server http://db.eternet.cc:5080 --provider github --format json

Gateway/Auth authority settings:

  • EAC_AUTH_SERVER_URL: default auth server used by eac auth commands.
  • EAC_GATEWAY_BASE_URL: gateway service catalog base URL (default https://api.eternet.cc).
  • EAC_GATEWAY_AUTH_SERVER_URL: gateway auth authority override when auth and API hosts differ.

Company mode authorization checks fail closed for missing tokens, expired tokens, and unreachable gateway refresh calls. Company mode now uses Windows secure storage by default. Set EAC_AUTH_MODE=local-dev to keep plaintext JSON (~/.eac/auth.json) explicitly, or use an auth write operation to migrate legacy JSON into the secure store.

Mutating service calls require --apply.

Legacy DB

Snapshot commands operate against the legacy DB snapshot service. Testing commands scaffold and refresh repo-local Firebird metadata test assets.

eac legacy-db snapshots status --format json
eac legacy-db snapshots versions --format json
eac legacy-db snapshots show --version <version> --format json
eac legacy-db snapshots download --version <version> --output <path> --format json
eac legacy-db snapshots create --apply --format json

eac legacy-db testing scaffold --workspace <repo> --snapshot-root tests/LegacyDb --format json
eac legacy-db testing refresh --workspace <repo> --snapshot-root tests/LegacyDb --version <version> --format json
eac legacy-db testing inspect --workspace <repo> --format json

Use legacy-db testing refresh for metadata fixtures. Use the legacy-db service catalog commands for full clone-session workflows.

Read-Only AI Reasoning

eac ai reason --workspace <repo> --backend copilot --prompt "Summarize current diagnostics"
eac ai reason --workspace <repo> --backend codex --prompt "Explain the remediation plan"

AI reasoning is advisory and read-only. It does not replace diagnose, remediation, or verify evidence.

Agent Workflow

flowchart TD
    A["Discover installed surface"] --> B["Load focused guidance"]
    B --> C["Inspect tooling health"]
    C --> D["Run fresh diagnose"]
    D --> E["Page stored diagnostics"]
    E --> F["Plan remediation or cleanup"]
    F --> G["Dry-run deterministic fixes"]
    G --> H["Apply only when EAC says safe"]
    H --> I["Manual or agent edits"]
    I --> J["Verify fresh evidence"]

Copyable baseline:

eac capabilities --format json
eac guidance show --id eac-agent-loop --format text
eac tooling inspect --workspace <repo> --profile all --format json
eac diagnose all --workspace <repo> --target <project-or-solution> --format json
eac diagnose list --workspace <repo> --from-run <run-id> --source eac --take 50 --format json
eac remediation status --workspace <repo> --from-run <run-id> --format json
eac remediation waves --workspace <repo> --from-run <run-id> --emit-plan .eac/remediation/waves.md --format json
eac remediation apply-codefix --workspace <repo> --from-run <run-id> --diagnostic <id> --format json
eac verify --workspace <repo> --target <change-name> --build-target <project-or-solution> --format json

Relationship With Agent Skills

The eac-harness agent skill is only a bootstrap layer. It tells an agent to check eac --version, discover eac capabilities, load eac guidance, use fresh diagnostics, and prefer EAC-owned deterministic remediation when safe. The CLI remains the versioned source of truth.

Release Flow

GitHub Releases are the review boundary. Publishing an eac-cli-v* release triggers the deterministic NuGet publishing workflow for the global tool.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
2.0.28 38 6/6/2026
2.0.27 51 6/5/2026
2.0.26 49 6/4/2026
2.0.25 74 6/3/2026
2.0.24 100 6/1/2026
2.0.23 106 5/30/2026
2.0.22 101 5/29/2026
2.0.21 100 5/28/2026
2.0.20 105 5/27/2026
2.0.19 102 5/26/2026
2.0.18 96 5/25/2026
2.0.17 96 5/24/2026
2.0.16 96 5/20/2026
2.0.15 113 5/19/2026
2.0.14 102 5/18/2026
2.0.13 96 5/17/2026
2.0.12 99 5/16/2026
2.0.11 104 5/15/2026
2.0.10 106 5/14/2026
2.0.9 106 5/13/2026
Loading failed