From 65f14a1a9f11ad87e0ab5f8c8bea16a5f3ded1a7 Mon Sep 17 00:00:00 2001 From: sepehr-safari Date: Sat, 11 Jul 2026 05:23:34 +0300 Subject: [PATCH] docs: architecture decision records (ADR-0001..0004) Captures the foundational decisions in Status/Context/Decision/Consequences form: independent implementation with a shared conformance contract (0001), macOS-first platform strategy (0002), native-rendered UI with no WebView (0003), and Zig on the Native SDK zero-config build (0004). Adds the ADR index. This satisfies the README/AGENTS links introduced in #7. Closes #4 --- docs/adr/0001-independent-implementation.md | 56 +++++++++++++++++++++ docs/adr/0002-macos-first-platforms.md | 44 ++++++++++++++++ docs/adr/0003-native-rendered-ui.md | 46 +++++++++++++++++ docs/adr/0004-zig-native-sdk-zero-config.md | 48 ++++++++++++++++++ docs/adr/README.md | 16 ++++++ 5 files changed, 210 insertions(+) create mode 100644 docs/adr/0001-independent-implementation.md create mode 100644 docs/adr/0002-macos-first-platforms.md create mode 100644 docs/adr/0003-native-rendered-ui.md create mode 100644 docs/adr/0004-zig-native-sdk-zero-config.md create mode 100644 docs/adr/README.md diff --git a/docs/adr/0001-independent-implementation.md b/docs/adr/0001-independent-implementation.md new file mode 100644 index 0000000..5ba04fe --- /dev/null +++ b/docs/adr/0001-independent-implementation.md @@ -0,0 +1,56 @@ +# ADR-0001 — Independent implementation with a shared conformance contract + +- **Status:** Accepted +- **Date:** 2026-07-11 + +## Context + +OCPP DebugKit already exists as `@ocpp-debugkit/toolkit`: a TypeScript library, +CLI, and web app that parse OCPP traces, detect failures, and generate reports — +deliberately offline, and explicitly *not* a CSMS, simulator, or active endpoint +tester. Studio is a native desktop application that claims exactly the live, +system-level territory the toolkit declares out of scope. + +The question is how the two relate. Options considered: + +1. **Share the toolkit's code** — e.g. wrap the TypeScript engine in a WebView + shell, or ship it as an embedded runtime. This couples Studio to a JavaScript + runtime and to the toolkit's release cadence, and undercuts the reason to + build natively at all. +2. **Reimplement the analysis engine in Zig, sharing nothing.** Two independent + implementations that risk silently diverging in behavior. +3. **Independent implementations bound by a specification contract.** Studio + reimplements the engine in Zig but is held to the toolkit's observable + behavior through shared fixtures and golden outputs. + +## Decision + +Studio is a **fully independent implementation** written in Zig. It shares **no +code** with the toolkit. The two projects meet only at a **conformance +contract**: + +- the trace input formats (JSON object, JSONL, bare array); +- the canonical normalized event model (`Event` / `Session` / `Failure`); +- the failure taxonomy (rule ids, severities, thresholds); +- the scenario fixtures and their expected results. + +Conformance is enforced mechanically: a pinned snapshot of the shared scenario +fixtures plus golden detected-failure sets is vendored into `conformance/`, and +CI runs Studio's engine over them and asserts an exact match. The contract is +versioned (`contract-v1`); it may later graduate to its own repository if drift +pressure appears, but not before it needs to. + +Where the toolkit's prose documentation and its code disagree, Studio mirrors the +**code** (the observable behavior), not the prose. + +## Consequences + +- Studio is free to be idiomatic Zig and to exploit native capabilities without + dragging along a JavaScript runtime or the toolkit's abstractions. +- A trace captured in Studio opens in the toolkit's inspector and vice versa — + the shared format is a real interoperability guarantee, and a marketing story: + two independent implementations, one format. +- The cost is a second implementation of the engine, and the discipline of + keeping goldens current. The conformance harness (milestone S2) is what makes + that discipline cheap and automatic. +- Behavioral divergence becomes a CI failure, not a silent bug. diff --git a/docs/adr/0002-macos-first-platforms.md b/docs/adr/0002-macos-first-platforms.md new file mode 100644 index 0000000..e365c1b --- /dev/null +++ b/docs/adr/0002-macos-first-platforms.md @@ -0,0 +1,44 @@ +# ADR-0002 — macOS-first, Linux in CI, Windows post-1.0 + +- **Status:** Accepted +- **Date:** 2026-07-11 + +## Context + +Studio targets desktop. The Native SDK supports macOS, Linux, and Windows, but +not equally: macOS is the deepest and most polished surface, Linux and Windows +are exercised in CI, and some niceties (native context menus, menu-bar extras) +are macOS-only today. Studio is also, for now, built by a single maintainer. + +Committing every UI decision to three release-grade platforms from day one would +triple the cost of every choice before the product has proven itself. Ignoring +the other platforms entirely would let cross-platform assumptions rot until a +painful port later. + +## Decision + +**macOS-first, with Linux validated in CI from day one, and Windows deferred +until after 1.0.** + +- Develop and polish on macOS. +- Keep Linux building and testing in CI on every change. The pure engine and the + headless view/model tests run cross-platform (`native test -Dplatform=null`), + and a Linux Xvfb job drives the running GUI through the automation harness — so + cross-platform breakage surfaces immediately, not at port time. +- The GPU-surface GUI is macOS-first; the Linux GUI is validated headlessly in CI + and promoted toward release quality around 1.0. +- Windows is out of scope until after 1.0. + +## Consequences + +- Fast iteration on the primary platform, without paying a three-platform tax on + every UI decision. +- Linux can never silently rot: CI compiles and exercises the engine there + continuously, which matters most for the pure-Zig OCPP engine. +- The CI split is asymmetric by design — full build + GUI smoke on Linux (Xvfb), + build on macOS, headless tests on both. This is a deliberate consequence of + where GUI automation is cheapest to run in CI, not a statement that Linux is + the primary target. +- Windows users have no build until post-1.0. Accepted for now. +- This decision is revisited at 1.0, when Linux is promoted to a first-class + release target and Windows is reconsidered. diff --git a/docs/adr/0003-native-rendered-ui.md b/docs/adr/0003-native-rendered-ui.md new file mode 100644 index 0000000..6f98f89 --- /dev/null +++ b/docs/adr/0003-native-rendered-ui.md @@ -0,0 +1,46 @@ +# ADR-0003 — Native-rendered UI, no WebView + +- **Status:** Accepted +- **Date:** 2026-07-11 + +## Context + +The Native SDK supports two UI architectures that can even coexist in one app: + +1. **WebView shell** — render a web frontend (React, Next, Vite, …) inside a + platform WebView, with a bridge to native Zig. This would let Studio reuse the + toolkit's existing React inspector components. +2. **Native-rendered** — declarative `.native` markup views driven by a Zig + `Model` / `Msg` / `update` loop, drawn by the SDK's own engine. No browser, no + WebView, no web frontend. + +The WebView route is the fastest path to a UI because it reuses existing web +code. But it reintroduces exactly what Studio was created to escape: a browser +engine, a JavaScript runtime, web performance ceilings, and a coupling to the +toolkit's frontend. It would make Studio a desktop wrapper around the web app +rather than a distinct native instrument. + +## Decision + +Studio's UI is **native-rendered**: `.native` markup views plus Zig logic on the +`UiApp` loop, drawn by the SDK engine. **No WebView, no web frontend, and no +reuse of the toolkit's React components** — consistent with the zero-code +relationship in [ADR-0001](0001-independent-implementation.md). + +Views stay declarative; all side effects (subprocesses, sockets, filesystem, +clipboard) flow through the update-side effects channel, keeping the UI a pure +function of the model. + +## Consequences + +- Instant startup, a small binary, low memory, and no GC pauses — the native + performance that justifies a separate desktop product, and what lets Studio + handle traces far larger than a browser tab. +- The UI must be built in the SDK's markup + Zig model, not in familiar web + tech. This is a real learning and authoring cost, and it means respecting the + engine's per-view budgets (virtualized lists for large event timelines). +- No dependency on a browser engine's release cadence or security surface. +- If a genuine need for embedded web content ever appears (rendering a + third-party HTML report, say), the SDK's WebView pane can be added for that + surface specifically — without making the app WebView-based. That would be a + new ADR. diff --git a/docs/adr/0004-zig-native-sdk-zero-config.md b/docs/adr/0004-zig-native-sdk-zero-config.md new file mode 100644 index 0000000..916a2d5 --- /dev/null +++ b/docs/adr/0004-zig-native-sdk-zero-config.md @@ -0,0 +1,48 @@ +# ADR-0004 — Zig + Native SDK on the zero-config build + +- **Status:** Accepted +- **Date:** 2026-07-11 + +## Context + +Studio needs a toolchain for a native desktop app that can open raw sockets, run +for days, render its own UI, and ship as a single binary. Two sub-decisions: + +1. **Language / framework.** The native-rendered UI decision + ([ADR-0003](0003-native-rendered-ui.md)) points at the Native SDK, whose + native surface is authored in Zig. Zig also fits the systems-level work Studio + needs (a WebSocket proxy, streaming parsers over gigabyte traces) with manual + memory control and no runtime. +2. **Build ownership.** The Native SDK CLI can scaffold either a *zero-config* + app (the CLI owns the build graph; no `build.zig` in the repo) or an *ejected* + app (`native eject` writes an owned `build.zig` / `build.zig.zon`). Zero-config + keeps the repo minimal but cedes build control to the CLI; ejecting grants + full control at the cost of owning framework-wiring boilerplate. + +## Decision + +Studio is written in **Zig on the Native SDK**, and stays on the **zero-config +build** until a concrete need forces ejection. + +- `app.zon` is the manifest; `src/` holds the app; the `native` CLI (`dev`, + `test`, `build`, `check`, `doctor`, `package`) owns the build. +- The framework is provided by the pinned `@native-sdk/cli` package, so CI needs + only Node, Zig, and `npm install -g @native-sdk/cli` — no framework checkout or + vendoring. +- The OCPP engine is organized so it stays pure Zig and headlessly testable, + independent of the UI and platform layers, behind a version-tagged protocol + boundary so OCPP 2.0.1 can be added without reworking 1.6J. + +## Consequences + +- A minimal repository: no build files to maintain, and upgrades come by bumping + one pinned CLI version. +- The trade-off is less build control. Custom build steps (extra link inputs, a + vendored C dependency such as a TLS library for the future secure proxy) are + not expressible until the app ejects. When that need is real — most likely + around live-capture TLS — Studio will `native eject` and own its `build.zig` in + a dedicated ADR-superseding change. +- Pinning the CLI version keeps a pre-1.0 SDK's churn from breaking `main` + unexpectedly; CI catches breakage on upgrade. +- Zig is itself pre-1.0. The toolchain is pinned to `0.16.0` and upgraded + deliberately. diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..f3de26c --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,16 @@ +# Architecture Decision Records + +This directory records the significant architecture decisions for OCPP DebugKit +Studio. Each ADR captures one decision in a consistent form — +**Status → Context → Decision → Consequences** — so the reasoning behind the +project's shape stays legible over time. + +ADRs are immutable once accepted: to change a decision, add a new ADR that +supersedes the old one rather than editing history. + +| ADR | Title | Status | +| --- | --- | --- | +| [0001](0001-independent-implementation.md) | Independent implementation with a shared conformance contract | Accepted | +| [0002](0002-macos-first-platforms.md) | macOS-first, Linux in CI, Windows post-1.0 | Accepted | +| [0003](0003-native-rendered-ui.md) | Native-rendered UI, no WebView | Accepted | +| [0004](0004-zig-native-sdk-zero-config.md) | Zig + Native SDK on the zero-config build | Accepted |