背景
最近、私が開発しているアプリケーションが、いわゆる開発の最後のフェーズに入ってきました。
主要な機能実装は一通り終わり、あとはシステムテストをしながら不具合を潰し、品質を上げていく段階です。
- 現在のアプリケーション
初期画面:
- デバッグ用のログの例
# HVE GUI 実行中画面 右下ペイン(実行中の課題 / エラーログ)
- 取得時刻: 2026-08-21 09:10:41
- 取得契機: 実行終了(returncode=0)
- ペイン見出し: 実行中の課題 (10)
---
[09:06:57] 2/APP-005: ツール失敗: [回復済み] view: Path does not exist (path=C:\GitHub\RoyalytyService2ndGen\docs\architectural-requirements-app-005.md)
[09:07:28] 2/APP-006: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1300, 1445])
[09:07:48] 2/APP-003: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1120, 1185])
[09:08:01] 2/APP-004: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1320, 1410])
[09:08:01] 2/APP-004: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1410, 1500])
[09:08:19] 2/APP-010: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1120, 1210])
[09:08:30] 2/APP-009: ツール失敗: [回復済み] apply_patch: Failed to apply patch: Error: Failed to find expected lines in C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md:
[09:08:30] 2/APP-001: ツール失敗: [回復済み] rg: timeout
[09:08:37] 2/APP-007: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1170, 1235])
[09:08:53] 2/APP-013: ツール失敗: [回復済み] view: view_range out of bounds (path=C:\GitHub\RoyalytyService2ndGen\docs\catalog\app-arch-catalog.md, view_range=[1170, 1230])
---
## 実行中に表示されたモーダルダイアログ
- class=QMessageBox title='完了' text='全てのタスクが終わりました | | '
これらから、以下のようなPromptをGitHub Copilotに投入して、見つかった原因を当然レビューもしながら、潰していたんです...
これまで私は、システムテストというものをかなり素直に考えていました。
画面から設定できるパラメーターをできるだけ多く入力する。
実際に処理を実行する。
ログを確認する。
必要であればDBの内容を期待値と比較する。
場合によってはExcelなどに結果を出して比較する。
こういう作業をきちんと積み重ねることが、システムテストの基本だと思っていました。
もちろん、この考え方自体が間違っているとは思っていません。
ただ、今回かなり長い時間テストを繰り返してみて、一つ違和感が出てきました。
人間が画面を操作することに、思った以上に時間を使っている。
しかも、時間を使っている割に、必ずしもテストの網羅性が高くなっているとは限らない。
ここが今回の出発点です。
注意点 / 前提
最初に書いておきます。
この記事は、私が現在開発しているアプリケーションで試した結果をベースにした、個人の見解です。
「コーディングエージェントにテストを任せれば、人間によるテストは不要になる」という話ではありません。
特にプロダクション環境では、
- セキュリティ
- 権限管理
- テストデータ
- 個人情報
- 外部システムへの影響
- コスト
- 再現性
- 監査証跡
など、別途考えなければいけないことがあります。
また、アプリケーションの種類によっても適用できる範囲はかなり変わります。
そのため、この記事で書いていることをそのまま一般化するのではなく、
「開発環境やテスト環境で、どこまで利用できるのか」
という観点で読んでいただくのがよいと思います。
まずはここまでで十分です。
整理・考え方
ここで一度、整理してみます。
今回考えているのは、単純なユニットテストの自動生成ではありません。
また、Playwrightなどを使った一般的なE2Eテスト自動化だけの話でもありません。
もう少し広い話です。
私が試したのは、
ソースコードを理解できるコーディングエージェントに、実際にアプリケーションを起動させ、操作させ、結果を確認させ、その結果から問題点まで分析させる
という方法です。
従来は、それぞれ別々の工程として考えていました。
アプリケーションを起動する
↓
画面を操作する
↓
結果を確認する
↓
ログを見る
↓
問題を調査する
↓
ソースコードを確認する
↓
修正案を考える
ところが、コーディングエージェントから見ると、この境界は必ずしも必要ありません。
ソースコードを見ることができる。
アプリケーションを実行できる。
ログを見ることができる。
ファイルを読むことができる。
スクリーンショットなどの証跡を残すこともできる。
そして、問題が見つかったら、そのまま原因となりそうなコードを調査できる。
ここが重要でした。
問題は「GUIテストができるか」ではありません。
テスト、観測、原因分析、修正計画が、一つのコンテキストにつながる可能性がある。
今回、私が面白いと思ったのはこの部分です。
人間が画面を操作し続けるテストは、思った以上に大変だった
今回のアプリケーションでは、私は何度も同じ画面を立ち上げていました。
例えば、
- テキスト1に値を入れる
- テキスト2に別の値を入れる
- テキスト3にも値を入れる
- ボタンを押す
- 結果を見る
- パラメーターを変更する
- もう一度実行する
という操作を繰り返します。
最初の数回はいいのですが、回数が増えてくると、
「さっき、このパターンは試したっけ」
という状態になってきます。
人間なので当然です。
さらに、画面を操作することそのものに集中していると、別の問題も起きます。
要求定義書や仕様書に書かれている項目を一つずつ確認しているうちに、目の前の項目だけを深掘りしすぎてしまうことがあります。
要するに、「点」に集中しすぎるわけです。
すると本来確認したかったユーザーシナリオや、システム全体としての振る舞いから少しずつ離れていく。
場合によっては、必要以上に細かい部分を追いかけて、結果としてオーバーエンジニアリングに近い状態になることもありました。
仕様書を書くことが悪いわけではありません。
むしろ重要です。
ただし、仕様書の各項目を確認することと、システムとして正しく動いていることを確認することは、必ずしも同じではありません。
実務では話が変わることが多いです。
1回のシステムテストに2時間近くかかっていた
今回作っているのは、プロンプトを利用し、内部でコーディングエージェントも利用するアプリケーションです。
そのため、1回のシステムテストがそれなりに重いです。
入力してボタンを押したら、数秒で答えが返ってくるタイプのアプリケーションではありません。
一連の処理を確認しようとすると、ケースによっては2時間近くかかることもありました。
その間、
- 画面を確認する
- ログを出す
- ログファイルを読む
- Visual Studioでソースコードを見る
- GitHub Copilotにログとコードを見せる
- 原因を調べる
- 修正する
- 再度テストする
ということを繰り返していました。
これを1か月近くやっていたわけです。
正直、かなり時間を使いました。
しかも、生成AIを利用するアプリケーションなので、テストそのものにもトークンやAPI利用料が発生します。
つまり、
時間も使うし、コンピューティングリソースも使うし、生成AIの利用コストもかかる。
それでもテストケース自体が十分だったかというと、必ずしもそうではありません。
ここでようやく、
「そもそも、このテスト方法そのものを見直した方がいいのでは」
と考えるようになりました。
きっかけは「画面のテストもAIでできますよね」という話だった
あるとき、他の人と話をしていて、画面テストの話になりました。
ブラウザアプリケーションであれば、Computer Useのような仕組みもありますし、Playwrightのようなツールもあります。
なので私は、
「まあ、画面のテスト自体はできますよね」
という話をしていました。
そのとき、ふと気がつきました。
自分が今作っているアプリケーションも、同じようにテストさせればいいのではないか。
別に、人間が画面を操作する必要はありません。
アプリケーションのソースコードはこちらにあります。
どのイベントで何が実行されるのかも追えます。
必要ならアプリケーションを起動する処理も書けます。
操作するためのコードも作れます。
私はそのコードを全部手で書く必要もありません。
コーディングエージェントに作らせることができます。
それなら、
「テストしてください」ではなく、「アプリケーションを起動して、この観点でシステムテストを実行し、証跡を保存し、結果を分析してください」
と指示すればよいのではないか。
そう考えて、実際に試してみました。
実際にやらせてみたら、人間より観点が広かった
結果として、これはかなり面白かったです。
Prompt:
`hve`の`gui`のアプリケーションのシステムテストを実行して、その動作結果の詳細なレポートを作成して、その調査結果をMarkdown形式で、`/work/{yyyy}-{mm}-{dd}-system-test-result.md`のファイルに保存をします。
詳細な実行プランを作成してください。テストの実行時間が長時間になる可能性が高いので、ステップ単位で、私が停止しても、再開をできるようにする。
## 目的
- `hve`の`gui`の画面で設定ができる、全ての設定項目の組み合わせで、**要求定義書**の全ての項目が、全て動作するのかを確認する。機能要件の確認が最重要で、非機能要件は範囲外
## 実施項目
- モデルは`Auto`
- 対象ワークフロー: ワークフローの`AAS`のStep 1とStep 2のみ
### 重要
- **捏造は絶対に禁止**です。存在しない問題を指摘してはいけません。情報源には必ず出展を提示してください。
GUIのアプリはOSのProcessとして動作していて...
その実行結果です。
# HVE GUI AAS Step 1/2 システムテスト結果
## 総合判定
**FAIL** — テスト実行自体は計画どおり完了したが、active FR 4件に対する確定FAILを3問題として検出した。
| 項目 | 結果 |
|---|---|
| 対象 | HVE GUI、Workflow=`aas`、Step=`1,2`、モデル設定=`Auto` |
| commit | `08c3b3b330f35cb1be605b3ecd06576cc6da9cd3` |
| HVE | `0.8.35` |
| 環境 | Windows 11 / Python 3.14.7 / PySide6 6.11.1 / pytest 9.1.1 |
| 隔離worktree | `C:\hve-systest-20260821-08c3b3b`(detached) |
| active FR | 230件(PASS 61 / FAIL 4 / BLOCKED 13 / NOT-APPLICABLE 152) |
| 確定問題 | 3件(Major 2 / Minor 1 / Critical 0) |
| 製品actual run | Step 1 ×1、Step 2 ×1、自動再実行0 |
| 外部live write | 0 |
| NFR | 範囲外 |
> 「テスト作業完了」と「製品合格」は別である。本作業はS01〜S10を完了したが、製品判定はFAILである。
## 対象と固定条件
- GUI上でAASだけを選択し、Step 1とStep 2だけを対象とした。
- モデル欄は`Auto`を維持し、設定値・wire値・実解決モデルを分けて記録した。
- 入力`docs/catalog/use-case-catalog.md`のidentityはGit blob `d1e23a9bf17792661c8d87e60e642c2b84971e90`を正本とした。
- Issue/PR/auto merge/Cloud Session/Work IQ writeなどの外部writeは実行しなかった。
- L4 actual runは各Step 1回のみ。中断・異常後の自動再実行は行っていない。
## GUI回帰と設定網羅
### GUI回帰
- GUI test file: **151 / 151完了**
- pytest: **1617 passed / 1 expected Windows skip / 0 failed**
- warning: **998件**。すべて`hve/gui/fonts.py:16`の`QFontDatabase()` DeprecationWarning。
- warning対象31ファイルの再実行: **31 / 31 rc=0**
### 設定インベントリ
| 観点 | 実測 |
|---|---:|
| `settings_store.defaults()` | 118 keys |
| 実入力widget | 461 |
| 設定binding | 20 sections / 96 keys |
| 有限シナリオ | 435 |
| valid / invalid | 411 / 24 |
| prerequisite有効化レコード | 128 |
### 有限網羅証明
| 網羅 | 結果 |
|---|---:|
| 1-wise | 374 / 374 |
| 制約付きpairwise | 245 / 245 |
| 必須interaction cluster | 15 / 15 |
| missing / extra / hash mismatch | 0 / 0 / 0 |
| 外部副作用ありシナリオ | 42(伝播確認、liveは42件BLOCKED) |
文字列・パス等の無限値域を「全値」とは主張せず、GUI実値域・同値クラス・1-wise・pairwise・要件指定clusterで有限化した。
## GUI実経路
QTestで`Workflow=AAS`、Step 1/2、`Next`を実クリックした。
- precheck: 1回、PASS、未充足0
- plan review: 1回、blocking gap 0
- Workbench stack: 0 → 1
- dry-run DAG:
- Wave 1: Step 1
- Wave 2: Step 2 / APP-001〜APP-014
- AAS以外のWorkflow選択: 0
- Step 1/2以外の実行: 0(非対象Stepはskip eventとしてのみ記録)
## AAS Step 1 actual run
| 項目 | 実測 |
|---|---|
| run | 1回、自動retryなし |
| return code | 0 |
| Step成功時間 | 386.1秒 |
| モデル | configured=`Auto` / wire=`auto` / resolved=`claude-opus-5` |
| assistant usage | 14 |
| token | input 1,289,481 / output 11,783 / reasoning 1,849 |
| AI Credit | 152.0300025 AIU |
| tool result | 28、failure 0 |
| 出力 | `docs/catalog/app-catalog.md` |
| SHA-256 | `8B0DC8110E270FE373EF4E16E220BAD47C723406AB4DA6E339929E134F65A734` |
構造検証:
- UC 26、Capability 13、APP 14
- traceability matrix: 26行 × 14 APP = 364 cells
- R=26 / S=117 / N=221
- 各UCのprimary `R`: 1件
- Decision Log: DEC-001〜DEC-017、連続表
- 入力Git blob不変
- product差分: `docs/catalog/app-catalog.md`のみ(+14/-4)
## AAS Step 2 actual run
| 項目 | 実測 |
|---|---|
| run | 1回、自動retryなし |
| return code | 0 |
| 所要時間 | 867.936秒 |
| fan-out | 14 expected / 14 done / 0 failed |
| モデル | configured=`Auto` / resolved=`gpt-5.6-luna` |
| assistant usage | 181 |
| token | input 11,535,601 / output 65,732 / reasoning 19,672 |
| AI Credit | 53.4856797 AIU |
| 出力 | `docs/catalog/app-arch-catalog.md` |
| SHA-256 | `11C086608891F82880F11AA7017A1F08CECD3F10F3DDBBEDF1B96DD6B1DF1BB0` |
構造検証:
- 固定A〜E見出し: PASS
- summary 14 / detail 14
- default適用 14 / unprocessed 0
- downstream partition: web-cloud 10 / batch 4 / overlap 0 / union 14
- 独立後処理検査: 31 / 31 PASS
- product差分はS07出力とS08出力の2ファイルのみ。staged/untracked product path 0。
## Workbench・観測
- GUI子processのreturn codeを0として受領し、完了通知を観測した。
- raw stats: 2,974 events、persistent JSONL: 2,973 events。
- seq 18の`debug_env`だけがstreamに存在し、永続化allowlistから除外された。seqはstrictly increasingかつunique。
- persistent JSONL: UTF-8 / LF / BOMなし / 1行1JSON。
- Step帰属は`2/APP-nnn`で保持され、FR-RTO-07のcurrent-commit回帰はGREEN。
- FR-GUI-19の終了後elapsed停止は、S04で`test_dag_status_widget.py`と`test_page_workbench_process_exit.py`をcurrent commit上で実行してGREEN。actual runでは終了前後の表示値を二時点採取していないため、実画面の停止値を直接実測したとは主張しない。
- APP別`instance_id`分離とpath allowlistに確定問題があるため、observability subsystem全体は合格ではない。
## active FR判定
機械正本は次のjoinである。
- 規範/source行: `work/run/20260821T-gui-aas-system-test/Issue-hve-gui-aas-step1-2/contracts/S02-requirements-scope.json`
- 最終status/evidence rule: `work/run/20260821T-gui-aas-system-test/Issue-hve-gui-aas-step1-2/contracts/S09-requirement-verdicts.json`
- join key: `requirement_id`
| Status | 件数 | 意味 |
|---|---:|---|
| PASS | 61 | 同一commitの今回実測または今回実行したcurrent-commit回帰で確認 |
| FAIL | 4 | 規範と同一commit実測が矛盾し、低コスト再現あり |
| BLOCKED | 13 | 外部write/live workplace/setup mutation/live context probeを未実行 |
| NOT-APPLICABLE | 152 | 別surface/workflow、または明示条件がfalse。PASS主張ではない |
### FAIL 4件
- `FR-RTO-01`, `FR-RTO-05` → SYS-001
- `FR-RTO-04` → SYS-002
- `FR-GUI-21` → SYS-003
### BLOCKED 13件
- GitHub外部write: `FR-CLI-30`, `31`, `32`, `33`, `34`, `75`
- 通常setup mutation: `FR-GUI-09`, `FR-MODEL-07`, `FR-MODEL-08`
- live Work IQ: `FR-QA-03`, `FR-QA-06`, `FR-QA-08`
- live context attribution: `FR-TS-11`
NOT-APPLICABLE 152件は、S02で対象外とした115件と、S09でactivation条件/別surfaceを確認した37件から成る。
## 確定問題
| ID | 重大度 | 要約 |
|---|---|---|
| SYS-001 | Major | APP fan-out全14子が`instance_id=aas`へ集約され、`aas#APP-nnn`に分離されない |
| SYS-002 | Major | 永続observabilityへ`$p`等のtool/PowerShell断片をpathとして保存(秘密値の保存は今回未観測) |
| SYS-003 | Minor | active FR-GUI-21のカテゴリー順・構成員とregistry/GUI/CLIが不一致 |
詳細・再現・hash・環境除外は`work/2026-08-21-system-test-issues.md`に記載した。
## 未確定・除外した信号
- SDK callback AssertionError: S07/S08で観測したが全子done・rc0。通常setupを再現していないため確定問題にしない。
- S08 tool failure 23件: 最終成果物31/31 PASS、14/14 child doneのため成果物欠落問題とはしない。
- lock改行テスト: Git blobはLF、Windows working treeだけCRLF。checkout表現として分離。
- ADA fanout marker固定件数: active FRに規範がなくAAS Step 1/2対象外。
- AASのAzure MCP接続: AASはFR-CLI-79のAzure-free allowlist外であり期待どおり。
## 主要証拠hash
| 証拠 | SHA-256 |
|---|---|
| S04 summary | `2C875BAA0036E56F0DBBEF9A223438B1B874A814B5DAB38566914006B610A8CA` |
| S05 summary | `D9EF86F77238FE761D04F59EAD7CAC11062975BC5B4194690C1BCD66CFC180F4` |
| S06 integrated | `477603B395C4D4F5D445A0C17F8FAD987675F323584A8D3F1D96CD097A9D867D` |
| S07 postprocess | `0D61B749BE9339BD73B83C3BA80B92DFDEC6AFF79B3935D176AF21E3FB94934B` |
| S08 execution | `B30C1CD990EB7B0A370F14F7C8DA73F5F4006949C399534B972CAD4D2764CE93` |
| S08 postprocess | `C7E0B9B35C7E4A10C0ECC2F5E6221671CADEAFB2E89CD654806B40085E1298CC` |
| S09 verdict overlay | `6F2FF3C861C9944E0AF33F38DA33C2A347915962417B54E17169D4B4FB48F421` |
| S09 RTO evidence | `FE07274DEC743F5126CEF4CF43CE1E396EB0A4BE4C8650D87143CBEF74B6F379` |
| S09 category evidence | `AC80DD0E711C9E1A3C7C226E3668F603B3C74B86F5DA42624F887F6B65F6F7C7` |
## 既知の制約
- 外部write・live Work IQ・通常setup更新・live context attributionは未実行であり、該当13件はBLOCKEDのまま。
- Workbench elapsed停止はcurrent-commit回帰で確認し、actual runの終了前後表示値は二時点採取していない。
- Windows単一環境の結果であり、NFR・クロスOS・性能目標判定は行っていない。
- `Auto`はStepごとに別モデルへ解決された。これは実測値であり、次回も同じモデルになる保証ではない。
<!-- validation-confirmed -->
もちろん万能ではありません。
ただ、私が自分で操作していたときよりも、テスト観点の網羅性が高いケースがありました。
例えば私は、ソフトウェアエンジニアとしてかなり長く仕事をしています。
経験があるので、時間をかければ多くのテスト観点を考えることはできます。
とはいえ、人間なので抜けます。
その日の集中力にも左右されます。
過去に似た不具合を経験していると、逆にそこに引っ張られることもあります。
コーディングエージェントに、
- ソースコード
- アプリケーションの目的
- テスト対象
- 想定するシナリオ
- 確認してほしい観点
を渡してテスト計画を作らせると、私がその場では思いつかなかった観点が出てくることがありました。
ここはかなり大きな違いでした。
重要なのは、
AIが人間より優秀だった、という単純な話ではない
ということです。
人間とエージェントでは、得意なことが違います。
私は「これは重要だろう」というところを経験から絞り込みます。
一方、エージェントは明示された情報やコードから、比較的機械的に観点を広げることができます。
この組み合わせが、テストではかなり相性がよいように感じました。
テスト結果そのものを証跡として残せる
もう一つよかったのが、証跡です。
例えばテストの実行中に、
- テキストログ
- 実行結果
- スクリーンショット
- 性能情報
- エラー情報
などを保存させることができます。
必要であれば動画を記録することも考えられます。
つまり、
「テストしました。問題ありませんでした」
ではなく、
何を実行して、どういう結果になったのか
をファイルとして残せます。
これは実務ではかなり重要です。
テスト自動化というと「人間が操作しなくてよくなる」という話になりがちですが、私はむしろこちらの方が重要ではないかと思っています。
テストの再現性と証跡を残しやすくなる。
さらに、その証跡を同じコーディングエージェントが読むことができる。
ここで次につながります。
テストから原因分析、修正計画までつながる
従来であれば、テストで問題を見つけた後に、人間がもう一度情報を集めます。
「このログを見てください」
「この操作をするとエラーになります」
「関連しそうなコードはここです」
という情報を、改めて開発者に渡すわけです。
ところが、同じコーディングエージェントがテストしているのであれば、その情報をすでに持っています。
もちろん、重要な証跡はファイルとして残した方がよいです。
ただ、少なくとも作業としては、
テスト
↓
問題検出
↓
ログ確認
↓
コード調査
↓
原因候補の整理
↓
修正計画
までをかなり連続して扱えます。
場合によっては、そのまま修正まで進めることもできます。
そこで、実行結果から、詳細な修正プランを作成してもらうと、以下の様なプランを作成してくれました。
## 分析結果
現時点では**修正・テスト実行・ファイル編集を一切行っていません**。添付の基準 commit `08c3b3b...` から現在の HEAD `148a45c4...` まで、対象コード/要件/ガイドに変更はなく、3件とも未解消です。
| 問題 | 判定 | 修正種別 | 主な根拠 |
|---|---|---|---|
| SYS-001 | 再現可能・根本原因確定 | bugfix | FR-RTO-01/05、共有 `RuntimeContext` と動的 fan-out の不整合 |
| SYS-002 | 再現可能・根本原因確定 | bugfix | FR-RTO-04、PowerShell raw token と path sanitizer の二重不足 |
| SYS-003 | 不一致確定・仕様選択あり | bugfix + 規範補正 | FR-GUI-21、registry、GUI/CLIテスト、履歴の不一致 |
親タスクは `task_scope=multi`、参照対象も9ファイルを超えるため、実装時は **SPLIT_REQUIRED** 相当です。
## 問題別の詳細分析
### SYS-001 — APP別 instance が統合される
処理経路は次のとおりです。
1. `hve/orchestrator.py::_attach_runtime_observability` はプロセス開始時に identity を1回設定。
2. `app_ids` が1件の場合だけ `workflow#APP-ID` とし、複数件/未指定では `workflow_id` のみ。
3. AAS Step 2 の動的展開後も、14子が共有する `Console._rt_context` は `instance_id="aas"` のまま。
4. `RuntimeMetricsRegistry` 自体は `instance_id` ごとに正しく分離するため、誤りは reducer ではなく**イベント構築前のidentity決定**にあります。
根拠:
- 規範: `hve-dev/requirement-definition.md:383`(FR-RTO-01)、`:387`(FR-RTO-05)
- identity設定: `hve/orchestrator.py::_attach_runtime_observability`
- イベント構築: `hve/runtime_observability.py::build_event`
- 子のAPPキー: `hve/fanout_expander.py::FanoutChildStep`
- 実行伝播: `hve/dag_executor.py::_run_with_semaphore`
- 実測判定: `work/run/20260821T-gui-aas-system-test/.../drivers/S09_rto_validate.py`
**採用する最小修正**
- `build_event` が `step_id="2/APP-001"` のような**完全なAPP-ID fan-out子**を認識し、そのイベントだけ `make_instance_id(workflow_id, app_id)` で上書きする。
- 親Stepや非APP fan-outは従来どおり。
- 既にAPP-specificなcontextは上書きしない。
- `RuntimeMetricsRegistry`、GUI reducer、CLI表示には手を加えない。
**採用しない案**
- 並列子の開始・終了ごとに共有 `Console.set_runtime_identity()` を変更する案
→ asyncio並列子間で競合するため不可。
- childごとのConsole/Registry新設
→責務変更が大きくYAGNI。
- 新CLIフラグ、環境変数、設定項目
→要件なし。
### SYS-002 — PowerShell断片がpathとして保存される
二段階の不足があります。
1. `hve/runner.py::_track_powershell_files`
- `-Path` 等の直後を `[^\s;|&]+` で取得。
- 外側のquoteを一部除去するだけで、`$p`、`` `$p)) ``、`docs/...md')` をpathとして発火。
2. `hve/runtime_observability.py::_to_repo_relative`
- 絶対path/`..` は拒否。
- しかし `$p` は構文上の相対pathとして受理。
今回の4実測値は、添付レポートと `S09_rto_validate.py` の判定が一致しています。
**採用する最小修正**
- 単一の字句判定を `runtime_observability` に置き、`$`、backtick、quote、丸括弧を含むtokenを非literalとして拒否。
- PowerShell producerで発火前に拒否し、raw stream/GUI表示/Step summaryへの混入を防ぐ。
- sanitizerでも同じ判定を再利用し、他producerから来ても永続化しない。
- 通常の引用付きliteral pathは外側quote除去後に従来どおり受理。
**採用しない案**
- PowerShell AST parser導入
- shell全般の完全構文解析
- path policy設定や例外allowlist
- 新規依存追加
いずれも今回の4ケースには不要です。
### SYS-003 — Category規範・実装・テストの分岐
履歴調査で時系列を確定しました。
1. `79818ab5`(2026-08-17)
- AI Agentを**末尾**へ追加。
- 構成員は `aag/aagd/aar`。
- CHANGELOGに「既存5カテゴリーの順序を維持」と明記。
2. `5950af8f`(2026-08-18)
- `ada` をAI Agentの先頭へ追加。
- AI Agentの位置は末尾のまま。
3. `635ed0db`(2026-08-18)
- 別目的の大規模commitでAI Agentを4番目へ移動。
- registryと一部GUIテストは変更。
- **要求定義書とCLI契約テストは未変更**。
- 位置変更理由はCHANGELOGにもありません。
したがって、現行4番目配置を規範と断定する根拠は不足しています。
**既定の正式契約**
1. Business Engineering
2. Architecture Design
3. Software Engineering
4. 既存ドキュメントのインポート
5. Knowledge Management
6. AI Agent: `ada/aag/aagd/aar`
理由:
- ユーザー指定どおり要求定義書を優先。
- 初回導入時の明示的な設計理由を維持。
- `ada` は全workflow分類義務と現行用途からAI Agentへ含める。
- 新カテゴリー追加は不要。
## 不明点と既定値
| 重要度 | 不明点 | 選択肢 | デフォルト | デフォルト理由 | 未回答時の影響 |
|---|---|---|---|---|---|
| 高 | SYS-003の正式順序 | A. 規範順+ADA追加 / B. 現行UI順を新規規範化 / C. 今回保留 | **A** | 要求定義優先、初回履歴に順序維持理由あり、4番目移動は規範未同期 | Aとして計画するが、実装開始前に変更可能 |
| 中 | 修正後に高コストの実モデルrunを再実施するか | A. deterministic local回帰のみ / B. AAS Step 1/2を再実行 | **A** | 14子dynamic fan-outはfake runnerで同一経路を再現可能。前回実測は約205.5 AIU、約1,254秒 | 製品コードの回帰は確認可能だが、実モデルE2E再認定は行わない |
回答が得られなかったため、以下は上記デフォルトで設計しています。
## 実行DAG
```mermaid
flowchart TD
G0[契約確認] --> A1[SYS-001 RED]
G0 --> B1[SYS-002 RED]
G0 --> C1[FR-GUI-21 規範補正]
A1 --> A2[イベントidentity実装]
A2 --> A3[SYS-001 GREEN]
B1 --> B2[PowerShell producer修正]
A3 --> B3[sanitizer修正]
B1 --> B3
B2 --> B4[SYS-002 GREEN]
B3 --> B4
C1 --> C2[Category RED]
C2 --> C3[registry順序修正]
C3 --> C4[GUIガイド]
C3 --> C5[CLIガイド]
C3 --> C6[ADA導線・技術ガイド]
C4 --> C7[Category GREEN・文書照合]
C5 --> C7
C6 --> C7
A3 --> A4[最終observability性能]
B3 --> A4
A4 --> V1[横断回帰]
B4 --> V1
C7 --> V1
V1 --> M1[要件テストmapping]
M1 --> M2[TDD inventory再生成]
M2 --> L1[CHANGELOG・PATCH版]
L1 --> F1[最終diff・version・回帰確認]
F1 -.明示承認時のみ.-> E1[隔離AAS実モデル再試験]
```
## 詳細タスク
概算は `R/P/I/V/F`(調査/計画/実装/検証/仕上げ、分)です。実測値ではありません。
| ID | 作業 | 編集ファイル | 依存・並列 | 完了条件 | 概算 |
|---|---|---|---|---|---:|
| G0 | SYS-003契約と実モデル再試験方針を確定 | なし | 起点 | 上記2判断を固定 | 5/5/0/0/5 |
| A1 | 14 APP dynamic fan-outのREDを追加 | `test_runtime_observability.py`、`test_dag_executor_fanout_deferred.py` | B1/C1と並列 | 現行コードで期待どおりFAIL | 10/5/20/10/5 |
| A2 | fan-out子イベントのinstanceをイベント単位で決定 | `runtime_observability.py` | A1後、B3より先 | 14子が`aas#APP-nnn`、親は`aas` | 10/5/20/10/5 |
| A3 | SYS-001 focused GREEN | 編集なし | A2後 | 単体+dynamic統合がPASS | 5/0/0/15/5 |
| B1 | 4実測tokenのREDを追加 | `test_runner_file_tracking.py`、`test_runtime_observability_store.py` | A1/C1と並列 | producerとsanitizerの双方でFAIL | 5/5/15/10/5 |
| B2 | PowerShell event発火前のtoken拒否 | `runner.py` | B1後、A2と並列 | 4値で`track_file/file_io`未発火、正常path維持 | 5/5/15/10/5 |
| B3 | 永続化直前のfail-closed拒否 | `runtime_observability.py` | A3・B1後 | 4値の`path` keyをdrop | 5/5/10/10/5 |
| B4 | SYS-002 focused GREEN | 編集なし | B2/B3後 | exact 4値+既存path回帰PASS | 5/0/0/15/5 |
| C1 | FR-GUI-21へADAを追加し、末尾順を明確化 | `requirement-definition.md` | A1/B1と並列 | 新規IDなし、改訂履歴を次版へ更新 | 10/5/10/5/5 |
| C2 | Category順・構成のREDを同期 | `test_workflow_categories.py`、`test_main_wizard_workflow_menu.py`、`test_page_workflow_select_categories.py` | C1後 | 現行4番目配置でFAIL | 5/5/20/10/5 |
| C3 | SSOTの順序だけを規範へ戻す | `workflow_registry.py` | C2後、A/B実装と並列 | 全13 workflowを重複なく分類 | 5/5/5/10/5 |
| C4 | GUI選択一覧を同期 | `hve-gui-orchestrator-guide.md`、`hve-gui-orchestrator-2step-flow.svg` | C3後、C5/C6と並列 | ADA、13件、規範順が一致 | 5/5/15/5/5 |
| C5 | CLI番号付きメニュー例を同期 | `hve-cli-orchestrator-guide.md` | C3後、C4/C6と並列 | 13件・実Step数・規範順がregistry一致 | 5/5/10/5/5 |
| C6 | ADAのGUI導線と明白な件数乖離を修正 | `09-agent-data-architecture.md`、`hve-technical-architecture.md` | C3後、C4/C5と並列 | ADAがAI Agentカテゴリと明記、12→13 | 5/5/10/5/5 |
| C7 | Category GREENと文書静的照合 | 編集なし | C4/C5/C6後 | GUI/CLI/category/helpテスト、リンク・ID照合PASS | 5/0/0/20/5 |
| A4 | 最終observability性能契約 | 編集なし | A3/B3後、他負荷と直列 | 2,000イベント `<0.2 ms/件`、recorder `<10 ms/件` | 5/0/0/15/5 |
| V1 | 影響範囲横断回帰 | 編集なし | A4/B4/C7後 | focused+fan-out+Console+orchestrator+GUIカテゴリPASS | 10/5/0/45/10 |
| M1 | 要件↔テストmappingへ実結果を反映 | `requirement-test-mapping.md` | V1後 | FR-RTO-01/04/05、FR-GUI-21に実在node IDと結果 | 10/5/10/5/5 |
| M2 | TDD inventoryを一度だけ再生成 | 下記5生成物 | M1後、他編集停止 | stale 0、`work/**`混入0 | 10/5/5/10/5 |
| L1 | PATCH版とCHANGELOGを同期 | `pyproject.toml`、`__init__.py`、`CHANGELOG.md` | M2後 | 現行0.8.35なら0.8.36、4箇所一致 | 5/5/10/5/5 |
| F1 | 最終品質ゲート | 編集なし | L1後 | diff、diagnostics、version、対象テスト、scope判定すべてPASS | 10/5/0/20/10 |
| E1 | 任意の隔離GUI AAS Step 1/2再試験 | 原則プロダクト編集なし | F1+明示承認 | 14 instance、invalid path 0、category一致 | 別途 |
### M2の機械生成対象
- `hve-test-inventory.csv`
- `hve-feature-inventory.csv`
- `hve-surface-inventory.csv`
- `hve-tdd-crosswalk-baseline.md`
- `hve-tdd-change-policy.md`
再生成前に、未追跡 `work` 内の入れ子コピーが入力へ混入しないこと、および並行セッションが `hve/*.py` を編集中でないことを確認します。
## 検証設計
### SYS-001
- exact APP fan-out unit:
- `2/APP-001` → `aas#APP-001`
- 非APP fan-out/親Stepは従来値
- 既にAPP-specificなcontextは変更しない
- dynamic integration:
- fake Step 1が14件の最小`app-catalog.md`を生成
- 実`DAGExecutor`がStep 2を14子へ動的展開
- モデル・SDK・ネットワークなし
- fan-outイベントのinstance集合が期待14件と完全一致
- run合算値は14子の合計
- 既存互換:
- seq単調増加
- `[hve:stats]`形式不変
- unknown kind集計不変
- NFR-RTO-01性能予算内
### SYS-002
exact regression data:
- `docs/architectural-requirements-app-006.md')`
- `$p))`
- `` `$p)) ``
- `$p`
追加確認:
- `docs/input.md`
- `'docs/input.md'`
- `src/./sub/../app.py`
- repo外絶対path
- `../` traversal
- forbidden tool引数・本文・envが引き続き非永続
### SYS-003
- `WORKFLOW_CATEGORIES`完全一致
- 全登録workflowが1カテゴリーに一度だけ所属
- AI Agentは末尾
- AI Agent構成員は `ada/aag/aagd/aar`
- GUI header順と直下4件
- CLI番号順・prefix・index解決
- 「その他」非表示
- 全workflowのhelp entry
- ガイド内ID集合・件数・リンク先の実在
## `users-guide` 更新判断
| 問題 | 更新 | 理由 |
|---|---|---|
| SYS-001 | 不要 | 表示仕様や利用手順は変えず、既存契約どおりに修復 |
| SYS-002 | 不要 | 内部の観測・sanitization境界で、利用者向け設定なし |
| SYS-003 | 必要 | GUI/CLIの選択順とADAの選択場所が利用者可視 |
### 更新対象外として確認のみ行うもの
- `README.md`: 既に13 workflowとADAを掲載
- `workflow-reference.md`: ADAを掲載済み
- `08-ai-agent.md`: AI Agentカテゴリの説明は矛盾なし
- `gui-03-workflow-selected-aas.png`: AI Agent位置が画面内に写っておらず再撮影不要
## オーバーエンジニアリング防止境界
- 新規設定、CLI引数、環境変数、依存パッケージを追加しない。
- Registry/Console/Dashboardの再設計をしない。
- shell完全parserを導入しない。
- Strategy/Factory/抽象path policyを作らない。
- category generatorや文書自動生成基盤を作らない。
- 今回観測されていないscreen/service fan-outへ仕様を拡張しない。
- 無関係な既存ガイド・画像・テスト失敗を便乗修正しない。
- Azure、GitHub、M365へのlive writeを行わない。
- 実モデル再試験は明示承認時だけ行う。
## 最終受入条件
- 3件すべての新規REDが修正前に期待理由で失敗し、修正後GREEN。
- SYS-001の14 APP instance集合が完全一致。
- SYS-002の4不正pathがproducerとpersistenceの双方から消える。
- SYS-003の規範・registry・GUI・CLI・ガイドが同一契約。
- NFR-RTO-01の既存性能予算を維持。
- TDD inventoryが最新かつ対象外path混入なし。
- HVE PATCH版とCHANGELOGが同期。
- 無関係差分、新規依存、新規設定面が0件。
## 検証結果
- 添付2文書、active要件4件、mapping、実装、関連テスト、users-guide、git履歴を照合済み。
- 現在HEADでも3件が未解消であることを確認済み。
- 今回は計画のみで、実装・テスト実行・外部操作は未実施です。
<!-- validation-confirmed -->
以上が、既定案に基づく実装前の詳細修正プランです。ご確認後に実行指示をいただくまで、コード変更には進みません。
計画策定のみ完了しました。実装はご指示いただくまで開始しません。
完了済み: *Analyze system test results* (1/4)
To Do 項目が 4 件作成されました
私にとっては、ここが一番大きな発見でした。
システムテストを単独の工程として考えるのではなく、
テストをソフトウェア開発ループの中に戻す
という考え方です。
コーディングエージェントから見ると、テストフェーズと実装フェーズを完全に分離する必要はないのかもしれません。
「ソースコードを読むAI」から「実行されたソフトウェアを見るAI」へ
コーディングエージェントというと、どうしてもソースコードを中心に考えます。
コードを書いてもらう。
リファクタリングしてもらう。
コードレビューしてもらう。
テストコードを書いてもらう。
もちろん、これらも有効です。
ただ、最終的にユーザーが利用するのはソースコードではありません。
実行されているアプリケーションです。
だから最後の品質確認では、
実際に動いているものを見て判断する
必要があります。
今回試してみて感じたのは、コーディングエージェントにそこまで見せてもよい、ということでした。
ソースコードだけではなく、
- 実行中のアプリケーション
- GUI
- ログ
- 性能
- 出力ファイル
- スクリーンショット
まで含めて一つの対象として見てもらう。
そうすると、コーディングエージェントが扱える範囲がかなり広がります。
クラウド上なら、さらに面白いことができそう
今回はPCの中で動くアプリケーションで試しています。
ただ、これがAzure上のアプリケーションだったらどうなるでしょうか。
例えばテスト専用のリソースグループを作ります。
そこに対象アプリケーションをデプロイします。
テストを実行します。
Azure Monitorなどからログやメトリクスを取得します。
必要であればApplication Insightsなどの情報も利用します。
さらに、MCPなどを通してクラウド側の情報を取得できるようにしておけば、
デプロイ
↓
テスト
↓
監視データ取得
↓
問題分析
↓
コード調査
↓
改善案
までを一つの流れとして扱える可能性があります。
SRE的な観点を持つエージェントと組み合わせることも考えられます。
もちろん、この段階になると権限設計はかなり重要です。
プロダクション環境で何でも実行できるようにするのは現実的ではありません。
コスト管理も必要です。
ただ、テスト用のAzure環境を明確に分離し、実行できる操作も限定するのであれば、十分検討できると思います。
実務では話が変わることが多いです。
だからこそ、「AIに全部任せる」ではなく、
AIが安全に操作できるテスト環境を設計する
という考え方になるのだと思います。
テスト専用のコンピューターを用意するという発想
今回の経験から、開発環境そのものについても考え方が少し変わりました。
これまでは自分のPCで、
- 開発
- ビルド
- アプリケーション実行
- テスト
- AIエージェント実行
を全部やっていました。
ただ、システムテストに2時間かかるのであれば、その間、自分のPCのCPUやメモリをテストに使い続ける必要はありません。
テスト専用のコンピューターを用意してしまえばよい。
例えばAzure上に、ある程度スペックの高いVirtual Machineを一台作ります。
そこにアプリケーションをインストールします。
テスト実行環境を構築します。
そして、コーディングエージェントにそこでテストを実行させる。
その間、私は自分のPCで別の仕事をする。
これはかなり合理的です。
クラウドVMなので、不要な時間は停止できます。
必要なときだけ高いスペックを利用することもできます。
開発者のPCを速くするという発想ではなく、
AIエージェントが作業するためのコンピューターを別に持つ
という考え方です。
生成AIを開発プロセスに入れていくと、こういう環境設計も今後は普通になっていくのかもしれません。
私自身、テストのやり方を変えようと思っている
少なくとも現在開発しているアプリケーションでは、今後のシステムテストについて、私はかなりやり方を変えるつもりです。
原則として、
- テストしたい観点を整理する
- コーディングエージェントにプロンプトとして渡す
- アプリケーションを実行させる
- テストさせる
- 証跡を保存させる
- 結果をレポートさせる
- 問題があれば改善計画まで作らせる
という流れに寄せていこうと考えています。
人間は、すべてのテスト画面をずっと監視しなくてもよい。
代わりに、
- テスト方針が妥当か
- エージェントが見落としているものはないか
- 結果を信頼できるか
- 修正してよい範囲はどこまでか
を確認する。
人間の役割がなくなるのではなく、役割が少し上のレイヤーに移るイメージです。
私はこの形の方が、少なくとも自分の時間の使い方としては合理的だと感じています。
ここまでの整理
ここまでの話を一度まとめます。
良い点
- 人間がGUIを繰り返し操作する時間を減らせる
- ソースコードからテスト観点を広げられる
- ログやスクリーンショットなどの証跡を残せる
- テスト結果から原因分析までつなげやすい
- 原因分析から修正計画まで同じコンテキストで進められる
- 長時間テストを別PCやクラウドVMに任せられる
- 実際に実行されるアプリケーションを対象に評価できる
注意点
- エージェントが生成したテスト観点が正しいとは限らない
- 人間による受け入れ確認が不要になるわけではない
- テスト環境とプロダクション環境は分離した方がよい
- クラウドを操作させる場合は権限設計が重要
- APIや生成AIを大量に呼ぶテストではコスト管理が必要
- 証跡を残さないと、後からテスト結果を検証しにくい
限界
- UXや「なんとなく使いにくい」といった感覚的評価は、人間の方が得意な場合がある
- エージェント自身が誤った判断をする可能性はある
- 外部システムを含む複雑なテストでは、環境準備そのものが難しい
- テスト対象によっては、従来のE2Eテストや専用テストツールの方が適している
つまり、万能ではありません。
ただ、従来のテストをすべて置き換えなくても、
「人間が毎回やっていた作業の一部をエージェントに渡す」
だけでも十分意味があると思います。
まとめ
今回、一番大きかったのは、
「これは人間がやるものだ」と勝手に決めていた作業が、思った以上に多かった
と気づいたことです。
GUIの操作。
システムテスト。
ログ確認。
スクリーンショット取得。
原因調査。
修正計画。
私はこれまで、それぞれ別の作業として考えていました。
でも、ソースコードを読めて、コマンドを実行できて、ファイルを読めるコーディングエージェントから見ると、これらはかなり連続した作業です。
最近は「Vibe Coding」という言葉もよく使われます。
ただ、私はもう少し広く、
プロンプトによって、開発工程のどこまでをコンピューターに実行させられるのか
と考えた方が面白いと思っています。
コードを書くことだけが対象ではありません。
テストもそうです。
調査もそうです。
品質確認もそうです。
私自身も、「これはAIには難しいだろう」「ここは専用ツールを使うしかないだろう」という先入観がかなりありました。
もちろん、専用ツールが適している場面は多くあります。
Playwrightを使った方がよいケースもありますし、従来型のテストフレームワークを使った方がよいケースもあります。
そこは極論にする必要はありません。
ただ、一度くらいは、
今手元にあるアプリケーションを起動するところから、テスト結果をまとめるところまで、コーディングエージェントに依頼してみる。
これは試してみてもよいと思います。
GitHub Copilotなど、すでに日常的に利用しているコーディングエージェントがあるのであれば、なおさらです。
いきなり大規模な仕組みを作る必要はありません。
まず一つのテストケースだけ任せてみる。
ログを取らせてみる。
スクリーンショットを保存させてみる。
そして、自分が実施した場合と結果を比較してみる。
まずはここまでで十分です。
そこで違いが見えれば、次にどこまで任せるのかを考えればよい。
私自身、今回の経験で、テストのやり方だけでなく、開発環境そのものの考え方まで少し変わり始めています。
生成AIによって変わるのは、コードの書き方だけではない。
開発工程をどの単位で人間が担当し、どの単位でエージェントに任せるのか。
その境界をもう一度考えてみる時期に来ているのかもしれません。


