From 2143d1ca70f354d90523bfc267828d028550a52c Mon Sep 17 00:00:00 2001 From: ShortArrow Date: Mon, 6 Jul 2026 13:50:13 +0900 Subject: [PATCH 1/3] docs(readme): rework for user-facing clarity (connection diagram, use-first statefulness, clearer scenario/script terms) --- README.md | 48 ++++++++++++++++----------- docs/README.jp.md | 48 ++++++++++++++++----------- docs/adr/0024-documentation-policy.md | 2 ++ 3 files changed, 58 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index a2d50de..1ac946f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Highlights - **Stateful, VISA-native CLI** - - **Stateful UX.** Register an alias once with `ivicli visa add psu1 ...`; subsequent commands operate on `psu1` without retyping the VISA resource. + - **A current device, like a shell's working directory.** `ivicli visa add psu1 ` registers an alias once; `ivicli visa use psu1` makes it *the current device*, so every later `visa query` / `write` / `script` needs no target at all — no VISA resource, not even the alias. - **VISA-compatible.** Parses standard `TCPIP::`, `USB::`, `GPIB::` resource strings without proprietary syntax. - **Automation-friendly.** Stdout carries data (including `--json`); stderr carries logs. Exit codes are POSIX-conventional. Shell completion ships for bash / zsh / PowerShell. - **Discover & inspect** @@ -19,9 +19,9 @@ - **Multiple backends.** Local NI-VISA, HiSLIP, VXI-11, raw TCP SOCKET, Fake (programmable + scenario playback), Replay (strict deterministic playback) — all behind a single `IIviBackend` port. - **Gateway servers.** Expose a local instrument over HiSLIP (`TCPIP::host::hislip0::INSTR`) or raw socket so remote PyVISA / NI-VISA clients can drive it without redeploying the test. - **Test without hardware** - - **Recordable scenarios.** `mock scenario record --from-script` captures the SCPI traffic of a script run; `IVICLI_REPLAY=` re-runs the same scripts deterministically without hardware. - - **Record once, replay forever.** Capture a real session with `IVICLI_CAPTURE`, convert it via `mock scenario import`, then drive any verb with `IVICLI_REPLAY=` — no more hardware time burned on regression checks. - - **Lint your scripts.** `visa lint foo.scpi` catches unknown SCPI roots (IEEE 488.2 + SCPI core) before you run them, without touching the instrument. + - **Run a mock instrument.** The `Fake` backend answers SCPI from a *scenario* — a scripted set of `query → response` rules — so `ivicli` (or your own VISA app) can talk to a stand-in with zero bench time. + - **Capture, then replay.** Record a live session (`IVICLI_CAPTURE=`) or a SCPI script run (`mock scenario record --from-script foo.scpi`) into a scenario, then re-run it deterministically with `IVICLI_REPLAY=` — no hardware burned on regression checks. + - **Run & lint SCPI scripts.** `visa script foo.scpi` runs a `.scpi` file (SCPI commands + inline assertions, [ADR 0027](docs/adr/0027-phase3-operator-automation.md)) against the current device; `visa lint foo.scpi` flags unknown SCPI roots (IEEE 488.2 + SCPI core) before you run it. - **Audit-friendly.** Set `IVICLI_CAPTURE=` and every backend operation streams to an NDJSON log for post-hoc inspection — `tail -f path | jq` or hand it to support. - **Control plane (HTTP / WebSocket API)** - **JSON HTTP API.** `ivicli api start` exposes a JSON HTTP API at `http://127.0.0.1:8080/v1` (with `/openapi/v1.json`) so AI agents, dashboards, and CI scripts can list devices / fire SCPI queries / read status without speaking VISA. @@ -135,32 +135,40 @@ ivicli completion powershell | Out-String | Invoke-Expression Once installed, `` expands subcommands, options, and runtime identifiers (device aliases, server names, scenario names). -## Architecture +## How it connects + +`ivicli` sits between a caller and an instrument. The four ways you use it: ```mermaid -flowchart LR - Cli["IviCli.Cli
(composition root)"] --> App["IviCli.Application
(handlers, ports)"] - Cli --> Server["IviCli.Server
(HiSLIP / SOCKET gateways)"] - Server --> App - Cli --> Infra["IviCli.Infrastructure
(TomlConfigStore, FilePidRegistry)"] - Infra --> App - Cli --> Backends["IviCli.Backends.*
(Fake / Local / HiSlip / Vxi11 / Socket / Replay)"] - Backends --> App - App --> Domain["IviCli.Domain
(value objects, entities, errors)"] - Server --> Domain - Backends --> Domain +flowchart TB + subgraph drive["1 · Drive real hardware"] + direction LR + u1["you / CI"] -->|"VISA — NI-VISA / HiSLIP / VXI-11 / SOCKET"| c1["ivicli"] --> i1["instrument
(LAN, USB/GPIB)"] + end + subgraph test["2 · Test without hardware"] + direction LR + u2["you / CI"] --> c2["ivicli"] -->|"Fake / Replay / mock container"| n2["no hardware"] + end + subgraph expose["3 · Expose a local instrument"] + direction LR + r3["remote PyVISA /
NI-VISA client"] -->|"HiSLIP / SOCKET gateway"| c3["ivicli"] --> i3["local instrument"] + end + subgraph control["4 · Control plane"] + direction LR + a4["AI agent /
dashboard / CI"] -->|"HTTP / WebSocket API"| c4["ivicli"] --> i4["instrument"] + end ``` -Dependency direction is one-way (Domain ← Application ← {Infrastructure, Backends, Server} ← Cli). The architecture-test suite (`tests/IviCli.Cli.Tests/Architecture/`) enforces it on every PR. +The internal layering (Clean Architecture + one-way dependency direction, enforced by an architecture-test suite) is documented for contributors in [ADR 0003](docs/adr/0003-architecture-style.md) and [ADR 0021](docs/adr/0021-repository-layout.md). ## Documentation -- [PRD](docs/PRD.md) — full product requirements ([日本語](docs/PRD.jp.md)) +- [PRD](docs/PRD.md) — full product requirements - [Architecture Decision Records](docs/adr/) — every Accepted decision behind the implementation. Start with [ADR 0003](docs/adr/0003-architecture-style.md) (architecture style), [ADR 0021](docs/adr/0021-repository-layout.md) (layer assemblies), [ADR 0007](docs/adr/0007-network-transport.md) (HiSLIP / SOCKET). - [Domain glossary](docs/domain-glossary.md) — the ubiquitous-language catalog - [Guides](docs/guides/) — task-oriented how-tos, starting with [Mock a VISA instrument](docs/guides/mock-a-visa-instrument.md) -- [Samples](docs/samples/) — drop-in scenarios + setup scripts (e.g. [PSU mock VISA device](docs/samples/psu/)) -- [Contributing](docs/CONTRIBUTING.md) — local dev loop, branching, hooks ([日本語](docs/CONTRIBUTING.jp.md)) +- [Samples](docs/samples/) — ready-made **mock instruments** for testing without hardware: drop-in scenarios + setup scripts (e.g. the [PSU mock](docs/samples/psu/)) +- [Contributing](docs/CONTRIBUTING.md) — local dev loop, branching, hooks ## Building from source diff --git a/docs/README.jp.md b/docs/README.jp.md index e647def..aa9e8c4 100644 --- a/docs/README.jp.md +++ b/docs/README.jp.md @@ -9,7 +9,7 @@ ## ハイライト - **状態保持型・VISA ネイティブな CLI** - - **状態保持型 UX.** `ivicli visa add psu1 ...` で alias を一度登録すれば、以降は `psu1` だけで操作できます。 + - **シェルのカレントディレクトリのような「現在の機器」.** `ivicli visa add psu1 ` で alias を一度登録し、`ivicli visa use psu1` で *現在の機器* に設定すれば、以降の `visa query` / `write` / `script` は対象指定が一切不要です(VISA リソースはもちろん alias すら書かなくてよい)。 - **VISA 互換.** 標準的な `TCPIP::` / `USB::` / `GPIB::` のリソース文字列を独自構文なしで扱います。 - **自動化指向.** stdout はデータ (`--json` 含む)、stderr はログ専用。終了コードは POSIX 慣習に従い、bash / zsh / PowerShell の補完をサポートします。 - **発見と可視化** @@ -19,9 +19,9 @@ - **複数バックエンド.** Local NI-VISA / HiSLIP / VXI-11 / raw TCP SOCKET / Fake (プログラム可能 + scenario 再生) / Replay (厳密な決定論的再生) を単一の `IIviBackend` port 越しに提供します。 - **ゲートウェイサーバ.** ローカル計測器を HiSLIP (`TCPIP::host::hislip0::INSTR`) または raw socket で公開し、リモートの PyVISA / NI-VISA クライアントから駆動できます。 - **ハードウェアなしでテスト** - - **シナリオ録画.** `mock scenario record --from-script` でスクリプト実行中の SCPI トラフィックを取得、`IVICLI_REPLAY=` で同じスクリプトをハードウェアなしに決定論的に再実行できます。 - - **一度録って何度でも再生.** `IVICLI_CAPTURE` で実機セッションを取り、`mock scenario import` で scenario に変換、以後 `IVICLI_REPLAY=` で同じ動作をハードウェア占有なしに再現できます。 - - **スクリプト Lint.** `visa lint foo.scpi` で IEEE 488.2 / SCPI core の語彙に対する未知のルートを計測器に触らずに検出します。 + - **モック計測器を動かす.** `Fake` backend は *scenario*(`query → response` ルールの集合)に従って SCPI に応答するので、`ivicli`(または自作の VISA アプリ)を実機なしのスタンドインと対話させられます。 + - **録って再生.** 実機セッション(`IVICLI_CAPTURE=`)または SCPI スクリプト実行(`mock scenario record --from-script foo.scpi`)を scenario に録り、`IVICLI_REPLAY=` で決定論的に再実行できます — 回帰チェックに実機を消費しません。 + - **SCPI スクリプトの実行と Lint.** `visa script foo.scpi` は `.scpi` ファイル(SCPI コマンド + インラインアサーション、[ADR 0027](adr/0027-phase3-operator-automation.md))を現在の機器に対して実行、`visa lint foo.scpi` は実行前に未知の SCPI ルート(IEEE 488.2 + SCPI core)を検出します。 - **監査向け.** `IVICLI_CAPTURE=` を設定するとすべての backend 操作が NDJSON ログにストリームされ、`tail -f path | jq` で後追い確認やサポート提出に利用できます。 - **コントロールプレーン (HTTP / WebSocket API)** - **JSON HTTP API.** `ivicli api start` で HTTP JSON API を `http://127.0.0.1:8080/v1` に公開(`/openapi/v1.json` 付き)。AI agent / ダッシュボード / CI スクリプトが VISA を喋らずに device 列挙・SCPI クエリ・status 取得できます。 @@ -135,32 +135,40 @@ ivicli completion powershell | Out-String | Invoke-Expression 導入後、`` でサブコマンド・オプション・実行時識別子(device alias、server 名、scenario 名)が展開されます。 -## アーキテクチャ +## どう繋がるか + +`ivicli` は呼び出し側と計測器の間に立ちます。使い方は次の 4 通りです: ```mermaid -flowchart LR - Cli["IviCli.Cli
(composition root)"] --> App["IviCli.Application
(handlers, ports)"] - Cli --> Server["IviCli.Server
(HiSLIP / SOCKET gateways)"] - Server --> App - Cli --> Infra["IviCli.Infrastructure
(TomlConfigStore, FilePidRegistry)"] - Infra --> App - Cli --> Backends["IviCli.Backends.*
(Fake / Local / HiSlip / Vxi11 / Socket / Replay)"] - Backends --> App - App --> Domain["IviCli.Domain
(value objects, entities, errors)"] - Server --> Domain - Backends --> Domain +flowchart TB + subgraph drive["1 · 実機を操作"] + direction LR + u1["you / CI"] -->|"VISA — NI-VISA / HiSLIP / VXI-11 / SOCKET"| c1["ivicli"] --> i1["計測器
(LAN, USB/GPIB)"] + end + subgraph test["2 · ハードウェアなしでテスト"] + direction LR + u2["you / CI"] --> c2["ivicli"] -->|"Fake / Replay / mock container"| n2["ハードウェアなし"] + end + subgraph expose["3 · ローカル計測器を公開"] + direction LR + r3["remote PyVISA /
NI-VISA client"] -->|"HiSLIP / SOCKET gateway"| c3["ivicli"] --> i3["ローカル計測器"] + end + subgraph control["4 · コントロールプレーン"] + direction LR + a4["AI agent /
dashboard / CI"] -->|"HTTP / WebSocket API"| c4["ivicli"] --> i4["計測器"] + end ``` -依存方向は一方向 (Domain ← Application ← {Infrastructure, Backends, Server} ← Cli)。アーキテクチャテスト (`tests/IviCli.Cli.Tests/Architecture/`) が PR ごとに違反を検知します。 +内部の層構成(Clean Architecture と一方向の依存方向、アーキテクチャテストで強制)は、コントリビュータ向けに [ADR 0003](adr/0003-architecture-style.md) と [ADR 0021](adr/0021-repository-layout.md) に記載しています。 ## ドキュメント -- [PRD](PRD.jp.md) — プロダクト要件 ([English](PRD.md)) +- [PRD](PRD.jp.md) — プロダクト要件 - [Architecture Decision Records](adr/) — Accepted な意思決定。読み始めの推奨: [ADR 0003](adr/0003-architecture-style.md) (アーキテクチャスタイル)、[ADR 0021](adr/0021-repository-layout.md) (層アセンブリ)、[ADR 0007](adr/0007-network-transport.md) (HiSLIP / SOCKET) - [Domain glossary](domain-glossary.md) — ユビキタス言語カタログ - [Guides](guides/) — タスク指向の how-to。まずは [Mock a VISA instrument](guides/mock-a-visa-instrument.md) -- [Samples](samples/) — そのまま投入できる scenario + セットアップスクリプト (例: [PSU mock VISA device](samples/psu/)) -- [Contributing](CONTRIBUTING.jp.md) — ローカル開発・ブランチ運用・hooks ([English](CONTRIBUTING.md)) +- [Samples](samples/) — ハードウェアなしでテストするための **モック計測器** 一式: そのまま投入できる scenario + セットアップスクリプト (例: [PSU モック](samples/psu/)) +- [Contributing](CONTRIBUTING.jp.md) — ローカル開発・ブランチ運用・hooks ## ソースからビルド diff --git a/docs/adr/0024-documentation-policy.md b/docs/adr/0024-documentation-policy.md index 3448891..6dd4543 100644 --- a/docs/adr/0024-documentation-policy.md +++ b/docs/adr/0024-documentation-policy.md @@ -75,6 +75,8 @@ and on the JP side: Both files share the same heading structure and section order so cross-reference is trivial. +**Navigation links point to the English canonical only.** When one document links to another (e.g. the README's documentation index linking to the PRD or CONTRIBUTING), it links the English file and does *not* append inline per-language variants such as `([日本語](...))`. Readers switch language via the target document's own top-of-file switcher. This keeps index lines from growing one entry longer per added language; the whole-document switcher header is the single place a language choice is offered. + ### 5. Domain glossary `docs/domain-glossary.md` is a living document: From d2b59beaf203923d0308615ef4956b9cac769d7c Mon Sep 17 00:00:00 2001 From: ShortArrow Date: Mon, 6 Jul 2026 16:39:00 +0900 Subject: [PATCH 2/3] docs(readme): link the official SCPI 1999.0 specification --- README.md | 2 +- docs/README.jp.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ac946f..0ebb4f0 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - **Test without hardware** - **Run a mock instrument.** The `Fake` backend answers SCPI from a *scenario* — a scripted set of `query → response` rules — so `ivicli` (or your own VISA app) can talk to a stand-in with zero bench time. - **Capture, then replay.** Record a live session (`IVICLI_CAPTURE=`) or a SCPI script run (`mock scenario record --from-script foo.scpi`) into a scenario, then re-run it deterministically with `IVICLI_REPLAY=` — no hardware burned on regression checks. - - **Run & lint SCPI scripts.** `visa script foo.scpi` runs a `.scpi` file (SCPI commands + inline assertions, [ADR 0027](docs/adr/0027-phase3-operator-automation.md)) against the current device; `visa lint foo.scpi` flags unknown SCPI roots (IEEE 488.2 + SCPI core) before you run it. + - **Run & lint SCPI scripts.** `visa script foo.scpi` runs a `.scpi` file — [SCPI](https://www.ivifoundation.org/downloads/SCPI/scpi-99.pdf) commands plus ivi-cli's inline assertions ([ADR 0027](docs/adr/0027-phase3-operator-automation.md)) — against the current device; `visa lint foo.scpi` flags unknown SCPI roots (IEEE 488.2 + SCPI core) before you run it. - **Audit-friendly.** Set `IVICLI_CAPTURE=` and every backend operation streams to an NDJSON log for post-hoc inspection — `tail -f path | jq` or hand it to support. - **Control plane (HTTP / WebSocket API)** - **JSON HTTP API.** `ivicli api start` exposes a JSON HTTP API at `http://127.0.0.1:8080/v1` (with `/openapi/v1.json`) so AI agents, dashboards, and CI scripts can list devices / fire SCPI queries / read status without speaking VISA. diff --git a/docs/README.jp.md b/docs/README.jp.md index aa9e8c4..05993ba 100644 --- a/docs/README.jp.md +++ b/docs/README.jp.md @@ -21,7 +21,7 @@ - **ハードウェアなしでテスト** - **モック計測器を動かす.** `Fake` backend は *scenario*(`query → response` ルールの集合)に従って SCPI に応答するので、`ivicli`(または自作の VISA アプリ)を実機なしのスタンドインと対話させられます。 - **録って再生.** 実機セッション(`IVICLI_CAPTURE=`)または SCPI スクリプト実行(`mock scenario record --from-script foo.scpi`)を scenario に録り、`IVICLI_REPLAY=` で決定論的に再実行できます — 回帰チェックに実機を消費しません。 - - **SCPI スクリプトの実行と Lint.** `visa script foo.scpi` は `.scpi` ファイル(SCPI コマンド + インラインアサーション、[ADR 0027](adr/0027-phase3-operator-automation.md))を現在の機器に対して実行、`visa lint foo.scpi` は実行前に未知の SCPI ルート(IEEE 488.2 + SCPI core)を検出します。 + - **SCPI スクリプトの実行と Lint.** `visa script foo.scpi` は `.scpi` ファイル([SCPI](https://www.ivifoundation.org/downloads/SCPI/scpi-99.pdf) コマンド + ivi-cli 独自のインラインアサーション、[ADR 0027](adr/0027-phase3-operator-automation.md))を現在の機器に対して実行、`visa lint foo.scpi` は実行前に未知の SCPI ルート(IEEE 488.2 + SCPI core)を検出します。 - **監査向け.** `IVICLI_CAPTURE=` を設定するとすべての backend 操作が NDJSON ログにストリームされ、`tail -f path | jq` で後追い確認やサポート提出に利用できます。 - **コントロールプレーン (HTTP / WebSocket API)** - **JSON HTTP API.** `ivicli api start` で HTTP JSON API を `http://127.0.0.1:8080/v1` に公開(`/openapi/v1.json` 付き)。AI agent / ダッシュボード / CI スクリプトが VISA を喋らずに device 列挙・SCPI クエリ・status 取得できます。 From f4283f37b25e7907c6b49b75c45522b84ed6874b Mon Sep 17 00:00:00 2001 From: ShortArrow Date: Mon, 6 Jul 2026 16:49:14 +0900 Subject: [PATCH 3/3] docs(readme): split connection diagram into four per-scenario diagrams --- README.md | 42 +++++++++++++++++++++++++----------------- docs/README.jp.md | 42 +++++++++++++++++++++++++----------------- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 0ebb4f0..d3dcf4e 100644 --- a/README.md +++ b/README.md @@ -139,24 +139,32 @@ Once installed, `` expands subcommands, options, and runtime identifiers (d `ivicli` sits between a caller and an instrument. The four ways you use it: +**1 · Drive real hardware** + +```mermaid +flowchart LR + u["you / CI"] -->|"VISA — NI-VISA / HiSLIP / VXI-11 / SOCKET"| c["ivicli"] --> i["instrument (LAN, USB/GPIB)"] +``` + +**2 · Test without hardware** + +```mermaid +flowchart LR + u["you / CI"] --> c["ivicli"] -->|"Fake / Replay / mock container"| n["no hardware"] +``` + +**3 · Expose a local instrument** + +```mermaid +flowchart LR + r["remote PyVISA / NI-VISA client"] -->|"HiSLIP / SOCKET gateway"| c["ivicli"] --> i["local instrument"] +``` + +**4 · Control plane** + ```mermaid -flowchart TB - subgraph drive["1 · Drive real hardware"] - direction LR - u1["you / CI"] -->|"VISA — NI-VISA / HiSLIP / VXI-11 / SOCKET"| c1["ivicli"] --> i1["instrument
(LAN, USB/GPIB)"] - end - subgraph test["2 · Test without hardware"] - direction LR - u2["you / CI"] --> c2["ivicli"] -->|"Fake / Replay / mock container"| n2["no hardware"] - end - subgraph expose["3 · Expose a local instrument"] - direction LR - r3["remote PyVISA /
NI-VISA client"] -->|"HiSLIP / SOCKET gateway"| c3["ivicli"] --> i3["local instrument"] - end - subgraph control["4 · Control plane"] - direction LR - a4["AI agent /
dashboard / CI"] -->|"HTTP / WebSocket API"| c4["ivicli"] --> i4["instrument"] - end +flowchart LR + a["AI agent / dashboard / CI"] -->|"HTTP / WebSocket API"| c["ivicli"] --> i["instrument"] ``` The internal layering (Clean Architecture + one-way dependency direction, enforced by an architecture-test suite) is documented for contributors in [ADR 0003](docs/adr/0003-architecture-style.md) and [ADR 0021](docs/adr/0021-repository-layout.md). diff --git a/docs/README.jp.md b/docs/README.jp.md index 05993ba..1b5a3ea 100644 --- a/docs/README.jp.md +++ b/docs/README.jp.md @@ -139,24 +139,32 @@ ivicli completion powershell | Out-String | Invoke-Expression `ivicli` は呼び出し側と計測器の間に立ちます。使い方は次の 4 通りです: +**1 · 実機を操作** + +```mermaid +flowchart LR + u["you / CI"] -->|"VISA — NI-VISA / HiSLIP / VXI-11 / SOCKET"| c["ivicli"] --> i["計測器 (LAN, USB/GPIB)"] +``` + +**2 · ハードウェアなしでテスト** + +```mermaid +flowchart LR + u["you / CI"] --> c["ivicli"] -->|"Fake / Replay / mock container"| n["ハードウェアなし"] +``` + +**3 · ローカル計測器を公開** + +```mermaid +flowchart LR + r["remote PyVISA / NI-VISA client"] -->|"HiSLIP / SOCKET gateway"| c["ivicli"] --> i["ローカル計測器"] +``` + +**4 · コントロールプレーン** + ```mermaid -flowchart TB - subgraph drive["1 · 実機を操作"] - direction LR - u1["you / CI"] -->|"VISA — NI-VISA / HiSLIP / VXI-11 / SOCKET"| c1["ivicli"] --> i1["計測器
(LAN, USB/GPIB)"] - end - subgraph test["2 · ハードウェアなしでテスト"] - direction LR - u2["you / CI"] --> c2["ivicli"] -->|"Fake / Replay / mock container"| n2["ハードウェアなし"] - end - subgraph expose["3 · ローカル計測器を公開"] - direction LR - r3["remote PyVISA /
NI-VISA client"] -->|"HiSLIP / SOCKET gateway"| c3["ivicli"] --> i3["ローカル計測器"] - end - subgraph control["4 · コントロールプレーン"] - direction LR - a4["AI agent /
dashboard / CI"] -->|"HTTP / WebSocket API"| c4["ivicli"] --> i4["計測器"] - end +flowchart LR + a["AI agent / dashboard / CI"] -->|"HTTP / WebSocket API"| c["ivicli"] --> i["計測器"] ``` 内部の層構成(Clean Architecture と一方向の依存方向、アーキテクチャテストで強制)は、コントリビュータ向けに [ADR 0003](adr/0003-architecture-style.md) と [ADR 0021](adr/0021-repository-layout.md) に記載しています。