# aalogcli

A `.NET Framework 4.8 / x86` CLI for reading the AVEVA / Wonderware **System Platform** binary log files (`*.aaLGX`) — built on the [aaOpenSource/aaLog](https://github.com/aaOpenSource/aaLog) reader library and tuned for LLM-driven debugging (last N records, last N minutes, explicit time ranges, incremental "unread" polling, JSON envelope output).

## Hard constraints

- **Default log directory is `C:\ProgramData\ArchestrA\LogFiles`**, which only exists on a host running System Platform / Application Server. Override with `--log-dir <path>` when reading copied logs.
- **`lib/aaLogReader.dll` must be provisioned before building** — `aaLog` is not on NuGet. See [Provisioning aaLogReader.dll](#provisioning-aalogreaderdll).
- **Target framework is `net48`, platform `x86`** to match the upstream library and stay aligned with `graccesscli`. Do not retarget to .NET 10 / x64.
- **Filtering is post-fetch**, so `--component` / `--level` / `--message` narrow the result set the library returns; they do not push down into the binary scan.

## Layout

```text
aalogcli/
  AaLog.Cli.slnx
  README.md            this file
  AGENTS.md            agent guidance for working in this folder
  lib/
    aaLogReader.dll    (not committed — see provisioning section)
  src/AaLog.Cli/
    AaLog.Cli.csproj
    Program.cs
    LogReaderFactory.cs
    Commands/          last, tail, range, unread, fields
    Output/            LogRecordDto, OutputWriter (human + llm-json)
    Filtering/         post-fetch substring/regex filter
  docs/
    usage.md           command surface, options, examples
    fields.md          LogRecord JSON field reference
```

## Resource index — by task

| Task | Go to |
| --- | --- |
| Agent rules for editing this CLI | [`AGENTS.md`](AGENTS.md) |
| Run the CLI / option reference / example invocations | [`docs/usage.md`](docs/usage.md) |
| `LogRecord` JSON field shape and types | [`docs/fields.md`](docs/fields.md) |
| Upstream reader library (license, source, build) | [aaOpenSource/aaLog on GitHub](https://github.com/aaOpenSource/aaLog) |
| LLM JSON envelope contract | [`docs/usage.md`](docs/usage.md#llm-json-envelope) |

## Provisioning `aaLogReader.dll`

The upstream library is GitHub-only, targets .NET 4.0, and ships with a legacy MSBuild `.csproj` plus a `packages.config` — none of which the modern .NET SDK 10 build pipeline restores cleanly. The recipe below rebuilds it as an SDK-style net48 project; this is the path that's been verified end-to-end on this repo.

If you have Visual Studio with full MSBuild + NuGet on PATH and prefer the upstream csproj as-is, that works too — just produce `aaLogReader.dll` somehow and drop it in `lib/`.

### SDK-style rebuild recipe (verified)

```powershell
# 1. Clone upstream sources somewhere outside this repo:
git clone https://github.com/aaOpenSource/aaLog.git $env:TEMP\aaLog

# 2. Create a sibling build folder with the SDK csproj from this repo's
#    aalogcli/lib/build/aaLogReader.csproj template (see below).
mkdir $env:TEMP\aaLogReader-build
copy <wwtools>\aalogcli\lib\build\aaLogReader.csproj $env:TEMP\aaLogReader-build\

# 3. Two source files need a one-line patch — they reference [CallerMemberName]
#    behind an #if NET45_OR_GREATER guard but never `using System.Runtime.CompilerServices;`.
#    Copy the templates from this repo's lib/build/patched/ into a sibling folder:
mkdir $env:TEMP\aaLogReader-build\patched
copy <wwtools>\aalogcli\lib\build\patched\*.cs $env:TEMP\aaLogReader-build\patched\

# 4. Build and copy out:
cd $env:TEMP\aaLogReader-build
dotnet build -c Release
copy bin\Release\net48\aaLogReader.dll <wwtools>\aalogcli\lib\aaLogReader.dll
```

The csproj template sets `<Deterministic>false</Deterministic>` (the upstream `AssemblyInfo.cs` uses `[assembly: AssemblyVersion("1.0.*")]`) and pins `Newtonsoft.Json 13.0.3` / `log4net 2.0.15` to match what `aalog` itself uses, so there are no transitive-version conflicts at runtime.

`aaLogReader.dll` only needs to land in `lib/`. `Newtonsoft.Json.dll` and `log4net.dll` are pulled in via NuGet by `aalog` itself and end up next to `aalog.exe` automatically.

## Build & run

```powershell
dotnet build src/AaLog.Cli/AaLog.Cli.csproj -p:Platform=x86 -c Release

# Last 50 records, human readable:
dotnet run --project src/AaLog.Cli/AaLog.Cli.csproj -- last

# Last 5 minutes, error-level only, JSON envelope for an LLM:
dotnet run --project src/AaLog.Cli/AaLog.Cli.csproj -- tail --minutes 5 --level Error --llm-json

# Explicit range with regex message filter:
dotnet run --project src/AaLog.Cli/AaLog.Cli.csproj -- range --from 2026-05-03T08:00 --to 2026-05-03T09:00 --message "Galaxy.*timeout" --regex --llm-json
```

The built executable is `bin\Release\net48\aalog.exe` — drop it on `PATH` and use `aalog last -n 100`.

## Maintenance

This README follows the project doctrine in [`../DOCS-GUIDE.md`](../DOCS-GUIDE.md). When you add a command, an option, or a new field to the DTO, update [`docs/usage.md`](docs/usage.md) and [`docs/fields.md`](docs/fields.md) in the same change. The root [`../CLAUDE.md`](../CLAUDE.md) holds one row pointing at this README — it should not need to change unless the tool's task surface changes.
