Files
Joseph Doherty 32f26272ae Initial commit: Wonderware / System Platform tools and reference
Five tools under one repo, all docs organized per DOCS-GUIDE.md:

- aalogcli: .NET 4.8 / x86 CliFx CLI for reading System Platform binary
  logs (*.aaLGX) for LLM debugging, built on aaOpenSource/aaLog. Commands:
  last, tail, range, unread, fields. Stable JSON envelope under --llm-json.
  Build template under lib/build/ for rebuilding aaLogReader.dll.

- aot: ArchestrA Object Toolkit 2014 v4.0 reference material. Dev guide
  (Markdown converted from CHM), API reference for the ArchestrA.Toolkit
  namespace, and the Monitor / Watchdog VS sample solutions.

- graccesscli: .NET 4.8 / x86 CliFx CLI that automates Galaxy
  configuration via the ArchestrA GRAccess COM interop. Includes session
  daemon, IPC protocol, and llm-json envelope contract.

- grdb: SQL/DDL exploration of the Galaxy Repository database. DDL
  captures, reusable queries, hierarchy / contained-name <-> tag-name
  translation notes.

- histdb: LLM-oriented reference for AVEVA Historian retrieval. INSQL
  linked-server, extension tables, every wwXxx time-domain extension,
  every retrieval mode, alarm/event SQL recipes, REST API. Distilled
  from the 243-page Historian Retrieval Guide.

Root contains:
- CLAUDE.md: thin index pointing into each tool's README.
- DOCS-GUIDE.md: doctrine for organizing docs for LLM consumption.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:22:20 -04:00

84 lines
5.2 KiB
Markdown

# AGENTS.md
Guidance for coding agents working in the `aalogcli` folder.
## Project Snapshot
This folder contains `aalogcli` (assembly name `aalog`), a `.NET Framework 4.8 / x86` CliFx-based CLI for reading AVEVA / Wonderware System Platform binary log files (`*.aaLGX`). It wraps the third-party reader library [`aaOpenSource/aaLog`](https://github.com/aaOpenSource/aaLog) and exposes it as `last`, `tail`, `range`, `unread`, and `fields` commands tailored for LLM-driven debugging (stable JSON envelope, bounded payloads, post-fetch filters).
For end-to-end command reference and examples, read [`docs/usage.md`](docs/usage.md). For the JSON shape of an emitted record, read [`docs/fields.md`](docs/fields.md). For the upstream reader's API (used by [`LogReaderFactory.cs`](src/AaLog.Cli/LogReaderFactory.cs) and the commands), see the [aaLog README](https://github.com/aaOpenSource/aaLog).
## Key Documentation
All paths are relative to this `aalogcli/` folder.
- [`README.md`](README.md) — tool entry point, hard constraints, build instructions.
- [`docs/usage.md`](docs/usage.md) — every command, every option, with worked examples for the LLM-JSON envelope.
- [`docs/fields.md`](docs/fields.md) — `LogRecordDto` field reference; the canonical shape of records in `--llm-json` output.
## Repository Layout
```text
aalogcli/
AaLog.Cli.slnx
lib/aaLogReader.dll (provisioned out-of-band — see README)
src/AaLog.Cli/
AaLog.Cli.csproj
Program.cs
LogReaderFactory.cs
Commands/
CommonOptions.cs (ReadCommandBase — shared options)
LastCommand.cs (`last` — last N records)
TailCommand.cs (`tail` — last N minutes)
RangeCommand.cs (`range` — explicit start/end)
UnreadCommand.cs (`unread`— incremental, cache-backed)
FieldsCommand.cs (`fields`— field reference printout)
Output/
LogRecordDto.cs (LLM-friendly subset of aaLogReader.LogRecord)
OutputWriter.cs (human single-line + llm-json envelope)
Filtering/
RecordFilter.cs (substring / regex over Component, Level, Message)
IsExternalInit.cs (C# 9 `init` polyfill for net48)
```
## Build And Test
Run commands from this `aalogcli` folder unless noted otherwise.
```powershell
dotnet build src/AaLog.Cli/AaLog.Cli.csproj -p:Platform=x86 -c Release
dotnet run --project src/AaLog.Cli/AaLog.Cli.csproj -- <args>
```
There is no test project at present. If you add one, mirror `graccesscli`'s convention: `tests/AaLog.Cli.Tests/AaLog.Cli.Tests.csproj`, `net48` / `x86`, xunit + Shouldly.
## Implementation Rules
- Keep the CLI targeting `net48` and `x86`. The upstream `aaLogReader` is net40 — net48 loads it cleanly, .NET 10 / x64 will not.
- Do **not** add a `[STAThread]` apartment requirement. Unlike `graccesscli`, `aaLogReader` is plain managed file I/O and runs fine on any thread.
- Construct readers through [`LogReaderFactory.Open`](src/AaLog.Cli/LogReaderFactory.cs) so every command honors `--log-dir` the same way.
- Always wrap the reader in `using` — it implements `IDisposable` and holds a `FileStream`.
- Treat the upstream library as authoritative for log decoding. Do not reimplement aaLGX parsing in this CLI.
- Filtering is **client-side**, after the library returns records. Do not push filter strings into `OptionsStruct.LogRecordPostFilters` from the CLI layer — surface stays flatter that way.
- Every read command must inherit [`ReadCommandBase`](src/AaLog.Cli/Commands/CommonOptions.cs) so `--log-dir` / `--component` / `--level` / `--message` / `--regex` / `--llm-json` stay consistent.
- `--llm-json` envelope shape is `{ query: {...}, count: N, records: [LogRecordDto, ...] }`. Preserve the envelope contract — agents may parse it positionally.
- `LogRecordDto` is the JSON contract. Adding a field is a non-breaking change; renaming or removing one is breaking — bump the docs in the same commit and call it out.
- C# language version is 9.0. `init` is supported through `IsExternalInit.cs`; do not use the `required` keyword.
- Use CliFx command patterns: `[Command]`, `[CommandOption]`, classes implement `ICommand`.
## Output Contracts
| Mode | Trigger | Shape |
| --- | --- | --- |
| Human | default | One line per record: `[localTs] [level] component (process#pid/tid) \| message` |
| LLM-JSON | `--llm-json` | `{ "query": {...}, "count": N, "records": [LogRecordDto, ...] }` |
The `query` object echoes the invocation parameters so an agent reading the JSON can confirm which window it actually got. `log_dir` in the query is the **resolved** directory (post-`--log-dir` override), so it doubles as a sanity check.
## Adding A New Command
1. Add `Commands/<Name>Command.cs` inheriting `ReadCommandBase` and implementing `ICommand`.
2. If it introduces a new query verb (e.g. `since-message-number`), wrap the corresponding `aaLogReader` method in `LogReaderFactory` or inline; document the verb in [`docs/usage.md`](docs/usage.md).
3. Add a row in [`README.md`](README.md) and [`docs/usage.md`](docs/usage.md). Do not modify `../CLAUDE.md` — the root index points at this README and that is sufficient.
4. Keep `--llm-json` envelope semantics identical across commands (`query`, `count`, `records`).