# AGENTS.md ## Mission Build a fully managed .NET 10 replacement for AVEVA Historian's `aahClientManaged` / `aahClient.dll` stack by reverse-engineering the native binary Historian protocol. The target is an in-process managed SDK that can replace the current .NET Framework/native sidecar used by `OtOpcUa.Driver.Historian.Wonderware`. ## Chosen Approach Use the reverse-engineering path from `instructions.md`: 1. Decompile `current\aahClientManaged.dll` to understand the managed wrapper surface, connection flow, query types, data models, error handling, and native calls. 2. Inspect `current\aahClient.dll` and the matching AVEVA install DLLs to map the native ABI and identify transport/framing responsibilities. 3. Capture traffic from real Historian sessions and derive the on-the-wire protocol for the required read-only operations. 4. Implement the protocol in a pure managed .NET 10 client. Do not pursue the REST API implementation unless explicitly asked. Do not build a P/Invoke shim as the primary solution; it is useful only as an analysis aid. ## Repository Layout This workspace is an SDK investigation folder, not a full application repo. - `instructions.md` - source planning document and decision record. - `current\` - the seven DLLs the existing sidecar links against today. - `aveva-install-x64\` - full 64-bit AVEVA Historian client-side DLL set. - `aveva-install-x86\` - full 32-bit AVEVA Historian client-side DLL set. Use `current\` first because it represents the deployed sidecar dependency set. Use `aveva-install-*` to compare architecture-specific behavior and locate adjacent client APIs. ## Required SDK Surface Keep the managed SDK narrowly scoped to the operations used in production: - `ReadRawAsync(tag, startUtc, endUtc, maxValues)` - `ReadAggregateAsync(tag, startUtc, endUtc, mode, interval)` - `ReadAtTimeAsync(tag, timestampsUtc)` - `ReadEventsAsync(startUtc, endUtc)` - `ProbeAsync()` The existing alarm-event write path is dormant. Do not implement write-back unless a new requirement is supplied. ## Reverse-Engineering Workflow ### 1. Managed Wrapper Analysis Use dnSpy or ILSpy on `current\aahClientManaged.dll`. Document: - Public types and methods used for connections and queries. - P/Invoke or native interop entry points. - Constructor arguments, enum values, flags, and default values. - Query argument structures for raw, aggregate, at-time, and event reads. - Returned sample/event models, quality fields, timestamp handling, and error propagation. Prefer producing small Markdown notes under a future `docs\reverse-engineering\` folder rather than relying on memory. ### 2. Native ABI Mapping Inspect `current\aahClient.dll` and compare with: - `aveva-install-x64\aahClient.dll` - `aveva-install-x86\aahClient.dll` - `aahClientCommon.dll` - `aahDataSetClient.dll` - `aahClientConfig.dll` Useful tools: - `dumpbin /exports` - Dependencies or Process Monitor - API Monitor - Detours or equivalent call hooks Document function names, calling conventions, pointer ownership, HRESULT/error patterns, string encodings, and architecture differences. ### 3. Wire Capture Capture real Historian sessions with Wireshark while running the existing Wonderware sidecar/client against a development Historian. Capture each scenario independently: - Connection open/close and health probe. - Raw history query. - Aggregate query for each required retrieval mode. - At-time/interpolated query. - Event query. - Error cases: bad tag, empty range, invalid credentials, server offline. For every capture, record: - Historian version and architecture. - Client DLL version and file hash. - Server host/port. - Query parameters. - Expected logical result set. - Packet capture filename. Do not commit sensitive packet captures, credentials, server names, or customer tag names. Sanitize before adding any fixtures or notes. ### 4. Protocol Model Derive and document: - Session handshake. - Authentication exchange, if present. - Message framing and length prefixes. - Message type identifiers. - Request/response correlation. - Endianness. - Timestamp encoding. - String encoding. - Numeric value encoding. - Quality/status encoding. - Error frame format. - Event payload format. Add version notes whenever behavior differs between the installed 2020 DLLs and newer Historian versions. ### 5. Managed Implementation Shape When implementation starts, use this project shape unless the real repo dictates otherwise: ```text src/AVEVA.Historian.Client/ AVEVA.Historian.Client.csproj HistorianClient.cs HistorianClientOptions.cs Models/ HistorianSample.cs HistorianAggregateSample.cs HistorianEvent.cs RetrievalMode.cs Protocol/ HistorianConnection.cs HistorianFrame.cs HistorianMessageType.cs HistorianProtocolReader.cs HistorianProtocolWriter.cs Transport/ TcpHistorianTransport.cs ClusterEndpointPicker.cs Internal/ BackoffPolicy.cs ``` Keep protocol parsing isolated from transport I/O so captured frames can be tested without a live Historian. ## Testing Expectations Start with deterministic tests around protocol encoding/decoding: - Golden byte fixtures for each message kind. - Round-trip tests for request builders. - Parser tests for captured and sanitized response frames. - Timestamp, quality, and string encoding edge cases. - Error frame parsing. Add live integration tests only behind explicit configuration, such as: - `HISTORIAN_HOST` - `HISTORIAN_PORT` - `HISTORIAN_USER` - `HISTORIAN_PASSWORD` - `HISTORIAN_TEST_TAG` Integration tests must skip cleanly when these values are not configured. ## Constraints - Keep the final SDK pure managed .NET 10. - Avoid adding native runtime dependencies to the production SDK. - Avoid broad API design. Implement only the operations listed above. - Treat AVEVA protocol details as version-sensitive; document assumptions. - Do not redistribute AVEVA binaries. - Do not commit credentials, proprietary captures, or customer data. - Do not delete or overwrite DLLs in `current\` or `aveva-install-*`. ## Definition of Done For the reverse-engineering phase: - Managed wrapper public surface and native entry points are documented. - Required query flows have sanitized captures or byte-level notes. - Message framing, request fields, response fields, and error frames are described well enough to implement parser tests. For the SDK phase: - The managed client implements the required read-only surface. - Unit tests cover protocol parse/build behavior. - Integration tests can validate against a configured live Historian. - The SDK can replace the existing sidecar call sites without requiring `aahClientManaged.dll` or `aahClient.dll` at runtime.