## Migrated Migrated from tickets/e2e-harness.md. No legacy review file was present at migration time. --- ## Decision E2E scope refinement: TUI/Panel PTY 自動化もこの Ticket の範囲に含める。 背景: - Panel mouse selection / Panel Quit latency の直近不具合では、focused unit test と code-path review だけで `done` 判定し、実端末経路の positive validation / measured validation が不足していた。 - 既存本文の「TUI バイナリを PTY で叩く方針は採らない」は、blind な固定入力スクリプトや GUI 代替としての ad hoc 操作を避ける意図として扱い、TUI/Panel の実プロセス・実端末入力を検証する automated PTY harness は本 Ticket に含める。 - Pod protocol/subprocess E2E と TUI/Panel PTY E2E は harness の部品は違うが、どちらも「実プロセスを spawn して user-visible boundary を検証する」ため、別 umbrella に分けず、この E2E harness Ticket の phase として扱う。 方針: - 固定 sleep + 固定 input だけの PTY script は採用しない。Harness は UI からの structured feedback を待ってから入力を送る。 - TUI/Panel には test-only / opt-in の observability route を追加する。これは UI action を bypass する command channel ではなく、状態観測・同期・失敗診断のための read-only probe とする。 - 実際の keyboard / mouse / Ctrl+C 入力は PTY 経由で送る。Probe は `first_draw`、`panel_snapshot_ready`、`rows_rendered`、`selection_changed`、`actionbar_changed`、`background_task_started/finished/aborted`、`quit_requested`、`terminal_cleanup_started/finished`、`exit` などの structured event を JSONL 等で吐く。 - Mouse E2E は `rows_rendered` の row key と screen rect を待ち、SGR mouse sequence を PTY に送って、`selection_changed` と screen/actionbar/detail の変化を確認する。 - Quit latency E2E は `panel_ready` / background work pending などの barrier event を待ってから `Ctrl+C` / `Ctrl+D` を送り、`quit_requested -> exit` の elapsed を測る。非本質 background work が abort/drop され、terminal cleanup が行われることも event で確認する。 - Screen output は `vt100`/`vte` 等の terminal parser で secondary oracle / artifact として保存する。主要同期は structured event に寄せる。 - Test probe は `--tui-test-events ` 等の明示的な hidden/dev/test flag か `e2e` feature 配下の構成で有効化し、通常実行・model context・Ticket authority・Pod protocol には影響させない。 - Failure artifact として event JSONL、input log、screen dump、stdout/stderr、runtime/data/workspace tmpdir の relevant tree、timing summary を保存する。 受け入れ条件の追加案: - `cargo test -p e2e --features e2e`(または同等の opt-in command)で実 `yoi panel` を PTY 上で起動し、structured probe feedback を待ってから入力する harness が動く。 - Panel row click E2E: rendered row rect を使って SGR mouse click を送り、selected row が変わることを assertion する。 - Panel quit latency E2E: ready/pending background work barrier 後に Quit 入力を送り、exit latency が閾値内で、nonessential background work が quit を block しないことを assertion する。 - Fixed sleep だけに依存する test は不可。ready/barrier event が来なければ screen dump と event log を artifact として失敗する。 - Probe は read-only observability であり、input/action path を bypass しないことを reviewer が確認する。 --- ## Decision E2E design decision: Playwright-like declarative test API と production binary 非混入を前提にする。 Decision: - E2E は ad hoc shell / fixed sleep script ではなく、Rust の独立 crate から宣言的に scenario を書ける構造にする。 - 例: `PanelHarness::spawn(...)`、`panel.wait_for(PanelReady)`、`panel.click(row("ticket", id))`、`panel.expect_selection(...)`、`panel.press(CtrlC)`、`panel.expect_exit_within(...)` のように、Playwright 的な wait/action/assertion API を提供する。 - Harness crate は production binary / normal library API から独立させる。想定配置は `tests/e2e/` または `crates/e2e_harness` + integration tests で、通常 build / release package / normal `yoi` binary に test harness logic を混ぜない。 - 本番 binary に混ぜる必要があるものは、原則として「既存 TUI state から read-only diagnostic event を emit するための最小 test hook」に限定する。その hook も normal runtime では無効で、明示 feature / hidden dev flag / cfg(test/e2e) 等でしか有効化しない。 - E2E harness は production code の内部関数を直接呼んで state mutation しない。入力は PTY、観測は structured test events / terminal screen parser、assertion は harness 側で行う。 - Structured events は protocol authority ではなく test observability artifact として扱う。Ticket/Pod authority や user-visible semantics を変えない。 Rationale: - 今回の Panel mouse / Quit latency の失敗は、unit/focused tests と code-path review だけでは user-visible terminal behavior を保証できないことを示した。 - 一方で fixed sleep + input script は再現性・診断性が低く、ready 状態や background work barrier を確認できない。 - Playwright-like API なら、test は「何を待ち、何を入力し、何を観測するか」を宣言的に表現でき、失敗時に event log / screen dump / timing artifact を残せる。 - Production binary への混入を避けることで、release behavior / binary size / authority surface / model-visible surfaces を汚さない。 Acceptance refinement: - E2E test author が fixed sleep ではなく `wait_for` / `expect` / `within` を使って Panel/TUI scenario を書ける。 - Mouse selection と Quit latency の regression は、この declarative harness API 上の scenario として表現される。 - Test-only observability route は opt-in であり、release/normal execution では無効または到達不能であることを reviewer が確認する。 - Failure artifact に scenario step、last observed events、screen snapshot、timing、binary path、workspace/runtime dirs が含まれる。 --- ## Decision Routing decision: implementation_ready Reason: - ユーザーが E2E harness を 1 Ticket として扱い、Playwright-like declarative API、structured feedback、production binary 非混入を前提に進めることを明示した。 - Ticket body は旧名/旧構成を含むが、thread decisions により現在の binding direction は明確化済み: Pod subprocess/protocol E2E と TUI/Panel PTY E2E を同じ harness Ticket の phase として扱う。 - 直近の Panel mouse selection / Panel Quit latency の regression から、実プロセス・実 PTY・structured event feedback・failure artifact を最小スライスに含める必要がある。 - `TicketRelationQuery` では durable blocker はなく、関連 Ticket は context link のみ。 - Orchestrator worktree は clean。implementation side effect は state acceptance 後に dedicated child worktree で行う。 Evidence checked: - Ticket body / thread decisions。 - relation records: `00001KV072V89` / `00001KV0723PC` への related links。 - orchestration plan records: なし。 - current workspace state: Orchestrator worktree clean、queued/inprogress work なし、implementation child Pods なし。 - project context: AGENTS guidance の E2E 未設計、prompt/resource boundary、production binary contamination 回避方針、直近 Panel validation failure records。 IntentPacket: Intent: - Yoi の E2E testing foundation を、実プロセス spawn と TUI/Panel PTY automation の両方を扱える opt-in harness として導入する。 - 最初の vertical slice は、Playwright-like declarative API、structured UI feedback、failure artifact、Panel mouse selection / Panel quit latency の regression scenario を実装できる形にする。 Binding decisions / invariants: - E2E harness は independent crate / test surface とし、normal release / normal `yoi` binary に harness logic を混ぜない。 - 本番 binary 側に必要な変更は opt-in read-only observability hook に限定する。UI action/state mutation を test hook で bypass しない。 - 実入力は PTY 経由で送る。structured event は synchronization / assertion / artifact のための観測情報であり、authority channel ではない。 - fixed sleep + fixed input だけの blind script を acceptance にしない。 - Pod/Ticket authority、prompt/resource boundary、public runtime behavior を E2E 都合で歪めない。 Requirements / acceptance criteria: - E2E author が Rust code で `spawn` / `wait_for` / `click` / `press` / `expect_*` / `within` を使って scenario を宣言的に書ける。 - Opt-in command(例: `cargo test -p e2e --features e2e` または同等)で通常 CI 既定から分離される。 - TUI/Panel test は panel ready / rows rendered / selection changed / background task / quit events など structured feedback を待ってから PTY input を送る。 - Panel mouse selection regression と Panel quit latency regression の少なくとも skeleton または minimal passing scenario が declarative harness 上で表現される。 - Failure artifact として event log、input log、screen dump、timing、binary path、workspace/runtime dirs が残る。 - Production binary contamination がないこと、または opt-in hook が normal runtime で無効/到達不能であることを reviewer が確認できる。 Implementation latitude: - `tests/e2e/` crate か `crates/e2e_harness` + integration tests のどちらに置くかは Coder が codebase constraints を見て選んでよい。ただし normal build/release contamination は避ける。 - PTY crate、terminal parser、event JSONL format、fixture workspace builder の具体設計は Coder が選んでよい。 - 最初の slice は full provider E2E ではなく、Panel/TUI harness と minimal process lifecycle / artifact foundation を優先してよい。 - 既存旧名 `INSOMNIA_*` / `pod` references は現在の `yoi` / config surface に合わせて整理してよい。 Escalate if: - read-only observability hook では足りず、production UI action path を test-only command channel で直接操作したくなる場合。 - normal release binary / normal CLI surface に test-only options を露出させる必要がある場合。 - workspace structure、Cargo package layout、Nix/package source filter に大きな変更が必要になる場合。 - Provider stub / Pod protocol E2E まで同時に広げないと Panel slice が進められない場合。 Validation: - focused E2E harness tests / example scenarios。 - `cargo fmt --check`。 - `git diff --check`。 - 変更範囲に応じて `cargo check --workspace --all-targets` または narrower package checks。 - 新 E2E command が opt-in で実行可能であることを report する。 Current code map: - `crates/yoi` / CLI launch path: hidden/test-only flag injection の候補。 - `crates/tui/src/multi_pod.rs`: Panel events / observable state emission の候補。 - `tests/e2e/` or new harness crate: declarative scenario API / PTY runner / artifact collector。 - root `Cargo.toml` / package metadata: opt-in package registration と release contamination check。 Critical risks / reviewer focus: - Harness code が production binary に混ざっていないこと。 - Observability hook が read-only で、input/action path を bypass していないこと。 - Test が fixed sleep 依存ではなく structured feedback / timeouts / artifacts を持つこと。 - Panel mouse / quit latency regression が今後「unit test だけで done」にならない程度の user-visible path を cover すること。 --- ## Intake summary ユーザー確認により、既存 E2E harness Ticket は Pod subprocess E2E と TUI/Panel PTY E2E を一つの実装対象として扱う。Playwright-like declarative API、independent opt-in crate、production binary 非混入、read-only structured observability、PTY input、failure artifact、Panel mouse / quit latency regression scenario が受け入れ方向として明確化済み。 --- ## State changed Ticket planning が完了しました。state planning -> ready。 --- ## State changed Ticket を `yoi ticket` が queued にしました。 --- ## State changed ユーザーが明示的に inprogress 化して進めることを承認した。Ticket evidence / relation records / OrchestrationPlan accepted plan / Orchestrator worktree clean state を確認済みで、blocking relation はない。Implementation side effect の前に state を inprogress として記録する。 --- ## Implementation report Implementation handoff started. - Worktree: `/home/hare/Projects/yoi/.worktree/e2e-harness` - Branch: `ticket-00001KSKBP9YG-e2e-harness` - Coder Pod: `coder-00001KSKBP9YG-e2e` - Scope: child worktree read、root `Cargo.toml` / `Cargo.lock` write、`tests/e2e` write、selected crates (`crates/tui`, `crates/yoi`, `crates/pod`, `crates/protocol`) write、`target` write、this Ticket record write。`.yoi/memory` や local/runtime/log/lock/secret-like `.yoi` paths は write scope に含めていない。 - Note: runtime launch validation のため `/home/hare/Projects/yoi` に非再帰 read grant を付けたが、Coder には root/original workspace を inspect/write/git/validate/merge/cleanup しないよう明示済み。 Next: - Coder は Playwright-like declarative E2E harness、read-only structured observability、PTY input、Panel mouse / quit latency regression scenario の first slice を実装する。 - Coder の commit / implementation_report / validation evidence を確認後、Reviewer を read-only 基本で起動する。 --- ## Decision Design note: Panel mouse E2E は raw SGR sequence を固定送信するだけでは不十分。 Rationale: - Harness が PTY に直接 `ESC [ < ... M` を書くと、実端末が mouse capture 有効時だけ mouse sequence を生成するという条件を bypass してしまい、今回のような「実端末ではイベントが来ない」系の不具合を見逃す可能性がある。 - Mouse E2E は locator/row rect を使って coordinate を決めるだけでなく、TUI が mouse capture mode を有効化したことも検証する必要がある。 追加すべき test harness 要件: - virtual terminal / screen parser は app output の terminal mode sequence(例: normal mouse + SGR mouse mode, `?1000h` / `?1006h` 相当)を tracking し、click helper は capture enabled が観測されていない場合に fail する。 - もしくは explicit read-only structured event と terminal output assertion の両方で `mouse_capture_enabled` を確認する。 - `click(row_selector)` は `rows_rendered` の rect から座標を選ぶが、raw SGR injection だけで成功扱いにしない。 - assertion は `selection_changed` event、screen/actionbar/detail の secondary oracle、そして workflow action が発火していないことを組み合わせる。 - これにより mouse selection E2E は面倒になるが、capture setup / coordinate mapping / event handling の user-visible path を分離して検証できる。 --- ## Decision Coder first-slice review: changes requested before external review. The initial E2E harness direction is promising, but it does not yet satisfy the regression-prevention bar from this Ticket. Required changes sent to Coder: 1. Mouse E2E must not pass solely by injecting raw SGR mouse bytes. Harness must track terminal mouse capture enable output (`?1000h` / `?1006h` equivalent) and fail `click(...)` / expose `expect_mouse_capture_enabled()` when capture was not observed. 2. Production binary contamination must be reduced. The TUI JSONL observer currently appears to be available in normal builds via `YOI_TUI_TEST_EVENTS`; prefer explicit `e2e-test` feature/cfg gating so release/normal binary has the hook compiled out. Report if feature gating is too large. 3. Quit latency E2E must wait for a real pending/background-work barrier at the moment of quit, not merely assert that `background_task_started` happened sometime earlier. Strengthen the scenario to prove Ctrl+C while pending work exists exits promptly. 4. Update implementation_report and validation evidence after changes. Reason: - The mouse selection regression specifically needs to catch missing terminal mouse capture, which raw SGR injection can bypass. - The user explicitly requested a structure where E2E harness logic does not mix into the production binary. - The quit latency regression needs measured user-visible behavior under a synchronized pending-work condition, not a loose startup smoke test. ---