Files
yaze/docs/z3ed/IT-08-IMPLEMENTATION-GUIDE.md
scawful 0447d6f8a1 feat: Implement auto-capture of screenshots and diagnostics on test failures
- Added a new helper function `CaptureHarnessScreenshot` to encapsulate SDL screenshot logic.
- Updated `ImGuiTestHarnessServiceImpl::Screenshot` to utilize the new screenshot helper.
- Enhanced `TestManager::CaptureFailureContext` to automatically capture screenshots and widget state on test failures.
- Introduced new fields in the `GetTestResultsResponse` proto for screenshot path, size, failure context, and widget state.
- Updated CLI and gRPC client to expose new diagnostic fields in test results.
- Ensured that screenshots are saved in a structured directory under the system's temp directory.
- Improved logging for auto-capture events, including success and failure messages.
2025-10-02 23:36:09 -04:00

24 KiB

IT-08: Enhanced Error Reporting Implementation Guide

Status: IT-08a Complete | IT-08b Complete | IT-08c Complete
Date: October 2, 2025
Overall Progress: 100% Complete (3 of 3 phases)


Phase Overview

Phase Task Status Time Description
IT-08a Screenshot RPC Complete 1.5h SDL-based screenshot capture
IT-08b Auto-Capture on Failure Complete 1.5h Integrate with TestManager
IT-08c Widget State Dumps Complete 45m Capture UI context on failure
IT-08d Error Envelope Standardization 📋 Planned 1-2h Unified error format across services
IT-08e CLI Error Improvements 📋 Planned 1h Rich error output with artifacts

Total Estimated Time: 5-7 hours
Time Spent: 3.75 hours
Time Remaining: 0 hours (Core phases complete)


IT-08a: Screenshot RPC COMPLETE

Date Completed: October 2, 2025
Time: 1.5 hours

Implementation Summary

What Was Built

Implemented the Screenshot RPC in the ImGuiTestHarness service with the following capabilities:

  1. SDL Renderer Integration: Accesses the ImGui SDL2 backend renderer through BackendRendererUserData
  2. Framebuffer Capture: Uses SDL_RenderReadPixels to capture the full window contents (1536x864, 32-bit ARGB)
  3. BMP File Output: Saves screenshots as BMP files using SDL's built-in SDL_SaveBMP function
  4. Flexible Paths: Supports custom output paths or auto-generates timestamped filenames (/tmp/yaze_screenshot_<timestamp>.bmp)
  5. Response Metadata: Returns file path, file size (bytes), and image dimensions

Technical Implementation

Location: /Users/scawful/Code/yaze/src/app/core/service/imgui_test_harness_service.cc

// Helper struct matching imgui_impl_sdlrenderer2.cpp backend data
struct ImGui_ImplSDLRenderer2_Data {
  SDL_Renderer* Renderer;
};

absl::Status ImGuiTestHarnessServiceImpl::Screenshot(
    const ScreenshotRequest* request, ScreenshotResponse* response) {
  // 1. Get SDL renderer from ImGui backend
  ImGuiIO& io = ImGui::GetIO();
  auto* backend_data = static_cast<ImGui_ImplSDLRenderer2_Data*>(io.BackendRendererUserData);
  
  if (!backend_data || !backend_data->Renderer) {
    response->set_success(false);
    response->set_message("SDL renderer not available");
## IT-08b: Auto-Capture on Test Failure ✅ COMPLETE

    ## IT-08b: Auto-Capture on Test Failure ✅ COMPLETE

    **Date Completed**: October 2, 2025  
    **Artifacts**: `CaptureFailureContext`, `screenshot_utils.{h,cc}`, CLI introspection updates

    ### Highlights

    - **Shared SDL helper**: New `CaptureHarnessScreenshot()` centralizes renderer
      capture and writes BMP files into `${TMPDIR}/yaze/test-results/<test_id>/`.
    - **TestManager integration**: Failure context now records ImGui window/nav
      state, widget hierarchy (`CaptureWidgetState`), and screenshot metadata while
      keeping `HarnessTestExecution` aggregates in sync.
    - **Graceful fallbacks**: When `YAZE_WITH_GRPC` is disabled we emit a harness
      log noting that screenshot capture is unavailable.
    - **End-user surfacing**: `GuiAutomationClient::GetTestResults` and
      `z3ed agent test results` expose `screenshot_path`, `screenshot_size_bytes`,
      `failure_context`, and `widget_state` in both YAML and JSON modes.

    ### Key Touch Points

    | File | Purpose |
    |------|---------|
    | `src/app/core/service/screenshot_utils.{h,cc}` | SDL renderer capture reused by RPC + auto-capture |
    | `src/app/test/test_manager.cc` | Auto-capture pipeline with per-test artifact directories |
    | `src/app/core/service/imgui_test_harness_service.cc` | Screenshot RPC delegates to shared helper |
    | `src/cli/service/gui_automation_client.*` | Propagates new proto fields to CLI |
    | `src/cli/handlers/agent/test_commands.cc` | Presents diagnostics to users/agents |

    ### Validation Checklist

    ```bash
    # Build (needs YAZE_WITH_GRPC=ON)
    cmake --build build-grpc-test --target yaze -j$(sysctl -n hw.ncpu)

    # Start harness
    ./build-grpc-test/bin/yaze.app/Contents/MacOS/yaze \
      --enable_test_harness --test_harness_port=50052 \
      --rom_file=assets/zelda3.sfc &

    # Queue a failing automation step
    grpcurl -plaintext \
      -import-path src/app/core/proto \
      -proto imgui_test_harness.proto \
      -d '{"target":"button:DoesNotExist","type":"LEFT"}' \
      localhost:50052 yaze.test.ImGuiTestHarness/Click

    # Fetch diagnostics
    z3ed agent test results --test-id <captured_id> --include-logs --format yaml

    # Inspect artifact directory
    ls ${TMPDIR}/yaze/test-results/<captured_id>/
    ```

    You should see a `.bmp` failure screenshot, widget JSON in the CLI output, and
    logs noting the auto-capture event. When the helper fails (e.g., renderer not
    ready) the harness log and CLI output record the failure reason.

    ### Next Steps

    - Wire the same helper into HTML bundle generation (IT-08c follow-up).
    - Add configurable artifact root (`--error-artifact-dir`) for CI separation.
    - Consider PNG encoding via `stb_image_write` if file size becomes an issue.

    ---
### Technical Implementation

**Location**: `/Users/scawful/Code/yaze/src/app/test/test_manager.{h,cc}`

**Key Changes**:

```cpp
// In HarnessTestExecution struct
struct HarnessTestExecution {
  // ... existing fields ...
  
  // IT-08b: Failure diagnostics
  std::string screenshot_path;
  int64_t screenshot_size_bytes = 0;
  std::string failure_context;
  std::string widget_state;  // IT-08c (future)
};

// In MarkHarnessTestCompleted()
if (status == HarnessTestStatus::kFailed || 
    status == HarnessTestStatus::kTimeout) {
  lock.Release();
  CaptureFailureContext(test_id);
  lock.Acquire();
}

// CaptureFailureContext implementation
void TestManager::CaptureFailureContext(const std::string& test_id) {
  absl::MutexLock lock(&harness_history_mutex_);
  auto it = harness_history_.find(test_id);
  if (it == harness_history_.end()) {
    return;
  }
  
  HarnessTestExecution& execution = it->second;
  
  // Capture execution context
  if (ImGui::GetCurrentContext() != nullptr) {
    ImGuiWindow* current_window = ImGui::GetCurrentWindow();
    const char* window_name = current_window ? current_window->Name : "none";
    ImGuiID active_id = ImGui::GetActiveID();
    
    execution.failure_context = absl::StrFormat(
        "Frame: %d, Active Window: %s, Focused Widget: 0x%08X",
        ImGui::GetFrameCount(), window_name, active_id);
  }
  
  // Set screenshot path placeholder
  execution.screenshot_path = absl::StrFormat(
      "/tmp/yaze_test_%s_failure.bmp", test_id);
}

Testing

The implementation will be validated when tests fail:

# 1. Build with changes
cmake --build build-grpc-test --target yaze -j8

# 2. Start test harness
./build-grpc-test/bin/yaze.app/Contents/MacOS/yaze \
  --enable_test_harness --test_harness_port=50052 \
  --rom_file=assets/zelda3.sfc &

# 3. Trigger a failing test
grpcurl -plaintext \
  -import-path src/app/core/proto \
  -proto imgui_test_harness.proto \
  -d '{"target":"nonexistent_widget","type":"LEFT"}' \
  127.0.0.1:50052 yaze.test.ImGuiTestHarness/Click

# 4. Query test results
grpcurl -plaintext \
  -import-path src/app/core/proto \
  -proto imgui_test_harness.proto \
  -d '{"test_id":"grpc_click_<timestamp>","include_logs":true}' \
  127.0.0.1:50052 yaze.test.ImGuiTestHarness/GetTestResults

Expected Response:

{
  "success": false,
  "testName": "Click nonexistent_widget",
  "category": "grpc",
  "executedAtMs": "1696357200000",
  "durationMs": 150,
  "screenshotPath": "/tmp/yaze/test-results/grpc_click_12345678/failure_1696357200000.bmp",
  "failureContext": "Frame: 1234, Active Window: Main Window, Focused Widget: 0x00000000"
}

Success Criteria

  • Failure context captured automatically on test failures
  • Screenshot path stored in test history
  • GetTestResults RPC returns failure diagnostics
  • No deadlocks (mutex released before calling CaptureFailureContext)
  • Proto schema updated with new fields

Retro Notes

  • Placeholder screenshot paths have been replaced by the shared helper that writes into ${TMPDIR}/yaze/test-results/<test_id>/ and records byte sizes.
  • Widget state capture (IT-08c) is now invoked directly from CaptureFailureContext, removing the TODOs from the original plan.

IT-08b: Auto-Capture on Test Failure 🔄 IN PROGRESS

Goal: Automatically capture screenshots and context when tests fail
Time Estimate: 1-1.5 hours
Status: Ready to implement

Implementation Plan

Step 1: Modify TestManager (30 minutes)

File: src/app/core/test_manager.cc

Add screenshot capture in MarkHarnessTestCompleted():

void TestManager::MarkHarnessTestCompleted(const std::string& test_id,
                                           ImGuiTestStatus status) {
  auto& history_entry = test_history_[test_id];
  history_entry.status = status;
  history_entry.end_time = absl::Now();
  history_entry.execution_time_ms = absl::ToInt64Milliseconds(
      history_entry.end_time - history_entry.start_time);
  
  // Auto-capture screenshot on failure
  if (status == ImGuiTestStatus_Error || status == ImGuiTestStatus_Warning) {
    CaptureFailureContext(test_id);
  }
}

void TestManager::CaptureFailureContext(const std::string& test_id) {
  auto& history_entry = test_history_[test_id];
  
  // 1. Capture screenshot
  std::string screenshot_path = 
      absl::StrFormat("/tmp/yaze_test_%s_failure.bmp", test_id);
  
  if (harness_service_) {
    ScreenshotRequest req;
    req.set_output_path(screenshot_path);
    
    ScreenshotResponse resp;
    auto status = harness_service_->Screenshot(&req, &resp);
    
    if (status.ok()) {
      history_entry.screenshot_path = resp.file_path();
      history_entry.screenshot_size_bytes = resp.file_size_bytes();
    }
  }
  
  // 2. Capture widget state (IT-08c)
  // history_entry.widget_state = CaptureWidgetState();
  
  // 3. Capture execution context
  history_entry.failure_context = absl::StrFormat(
      "Frame: %d, Active Window: %s, Focused Widget: %s",
      ImGui::GetFrameCount(),
      ImGui::GetCurrentWindow() ? ImGui::GetCurrentWindow()->Name : "none",
      ImGui::GetActiveID());
}

Step 2: Update TestHistory Structure (15 minutes)

File: src/app/core/test_manager.h

Add failure context fields:

struct TestHistory {
  std::string test_id;
  std::string test_name;
  ImGuiTestStatus status;
  absl::Time start_time;
  absl::Time end_time;
  int64_t execution_time_ms;
  std::vector<std::string> logs;
  std::map<std::string, std::string> metrics;
  
  // IT-08b: Failure diagnostics
  std::string screenshot_path;
  int64_t screenshot_size_bytes = 0;
  std::string failure_context;
  std::string widget_state;  // IT-08c
};

Step 3: Update GetTestResults RPC (30 minutes)

File: src/app/core/service/imgui_test_harness_service.cc

Include screenshot path in results:

absl::Status ImGuiTestHarnessServiceImpl::GetTestResults(
    const GetTestResultsRequest* request,
    GetTestResultsResponse* response) {
  
  const auto& history = test_manager_->GetTestHistory(request->test_id());
  
  // ... existing result population ...
  
  // Add failure diagnostics
  if (!history.screenshot_path.empty()) {
    response->set_screenshot_path(history.screenshot_path);
    response->set_screenshot_size_bytes(history.screenshot_size_bytes);
  }
  
  if (!history.failure_context.empty()) {
    response->set_failure_context(history.failure_context);
  }
  
  return absl::OkStatus();
}

Step 4: Update Proto Schema (15 minutes)

File: src/app/core/proto/imgui_test_harness.proto

Add fields to GetTestResultsResponse:

message GetTestResultsResponse {
  string test_id = 1;
  TestStatus status = 2;
  int64 execution_time_ms = 3;
  repeated string logs = 4;
  map<string, string> metrics = 5;
  
  // IT-08b: Failure diagnostics
  string screenshot_path = 6;
  int64 screenshot_size_bytes = 7;
  string failure_context = 8;
  string widget_state = 9;  // IT-08c
}

Testing

# 1. Build with changes
cmake --build build-grpc-test --target yaze -j8

# 2. Start test harness
./build-grpc-test/bin/yaze.app/Contents/MacOS/yaze \
  --enable_test_harness --test_harness_port=50052 \
  --rom_file=assets/zelda3.sfc &

# 3. Trigger a failing test
grpcurl -plaintext \
  -import-path src/app/core/proto \
  -proto imgui_test_harness.proto \
  -d '{"target":"nonexistent_widget","type":"LEFT"}' \
  127.0.0.1:50052 yaze.test.ImGuiTestHarness/Click

# 4. Check for screenshot
ls -lh /tmp/yaze_test_*_failure.bmp

# 5. Query test results
grpcurl -plaintext \
  -import-path src/app/core/proto \
  -proto imgui_test_harness.proto \
  -d '{"test_id":"grpc_click_<timestamp>"}' \
  127.0.0.1:50052 yaze.test.ImGuiTestHarness/GetTestResults

# Expected: screenshot_path and failure_context populated

Success Criteria

  • Screenshots auto-captured on test failure
  • Screenshot path stored in test history
  • GetTestResults returns screenshot metadata
  • No performance impact on passing tests
  • Screenshots cleaned up after test completion (optional)

IT-08c: Widget State Dumps COMPLETE

Date Completed: October 2, 2025
Time: 45 minutes

Implementation Summary

Successfully implemented comprehensive widget state capture for test failure diagnostics.

What Was Built

  1. Widget State Capture Utility (widget_state_capture.h/cc):

    • Created dedicated service for capturing ImGui widget hierarchy and state
    • JSON serialization for structured output
    • Comprehensive state snapshot including windows, widgets, input, and navigation
  2. State Information Captured:

    • Frame count and frame rate
    • Focused window and widget IDs
    • Hovered widget ID
    • List of visible windows
    • Open popups
    • Navigation state (nav ID, active state)
    • Mouse state (buttons, position)
    • Keyboard modifiers (Ctrl, Shift, Alt)
  3. TestManager Integration:

    • Widget state automatically captured in CaptureFailureContext()
    • State stored in HarnessTestExecution::widget_state
    • Logged for debugging visibility
  4. Build System Integration:

    • Added widget_state_capture sources to app.cmake
    • Integrated with gRPC build configuration

Technical Implementation

Location: /Users/scawful/Code/yaze/src/app/core/widget_state_capture.{h,cc}

Key Features:

struct WidgetState {
  std::string focused_window;
  std::string focused_widget;
  std::string hovered_widget;
  std::vector<std::string> visible_windows;
  std::vector<std::string> open_popups;
  int frame_count;
  float frame_rate;
  ImGuiID nav_id;
  bool nav_active;
  bool mouse_down[5];
  float mouse_pos_x, mouse_pos_y;
  bool ctrl_pressed, shift_pressed, alt_pressed;
};

std::string CaptureWidgetState() {
  // Captures full ImGui context state
  // Returns JSON-formatted string
}

Integration in TestManager:

void TestManager::CaptureFailureContext(const std::string& test_id) {
  // ... capture execution context ...
  
  // Widget state capture (IT-08c)
  execution.widget_state = core::CaptureWidgetState();
  
  util::logf("[TestManager] Widget state: %s", 
             execution.widget_state.c_str());
}

Output Example

{
  "frame_count": 1234,
  "frame_rate": 60.0,
  "focused_window": "Overworld Editor",
  "focused_widget": "0x12345678",
  "hovered_widget": "0x87654321",
  "visible_windows": [
    "Main Window",
    "Overworld Editor",
    "Debug"
  ],
  "open_popups": [],
  "navigation": {
    "nav_id": "0x00000000",
    "nav_active": false
  },
  "input": {
    "mouse_buttons": [false, false, false, false, false],
    "mouse_pos": [1024.5, 768.3],
    "modifiers": {
      "ctrl": false,
      "shift": false,
      "alt": false
    }
  }
}

Testing

Widget state capture will be automatically triggered on test failures:

# 1. Build with new code
cmake --build build-grpc-test --target yaze -j8

# 2. Start test harness
./build-grpc-test/bin/yaze.app/Contents/MacOS/yaze \
  --enable_test_harness --test_harness_port=50052 \
  --rom_file=assets/zelda3.sfc &

# 3. Trigger a failing test
grpcurl -plaintext \
  -import-path src/app/core/proto \
  -proto imgui_test_harness.proto \
  -d '{"target":"nonexistent_widget","type":"LEFT"}' \
  127.0.0.1:50052 yaze.test.ImGuiTestHarness/Click

# 4. Query results - will include widget_state field
grpcurl -plaintext \
  -import-path src/app/core/proto \
  -proto imgui_test_harness.proto \
  -d '{"test_id":"<test_id>","include_logs":true}' \
  127.0.0.1:50052 yaze.test.ImGuiTestHarness/GetTestResults

Success Criteria

  • Widget state capture utility implemented
  • JSON serialization working
  • Integrated with TestManager failure capture
  • Added to build system
  • Comprehensive state information captured
  • Proto schema already supports widget_state field

Benefits for Debugging

The widget state dump provides critical context for debugging test failures:

  • UI State: Know exactly which windows/widgets were visible
  • Focus State: Understand what had input focus
  • Input State: See mouse and keyboard state at failure time
  • Navigation: Track ImGui navigation state
  • Frame Timing: Frame count and rate for timing issues

IT-08c: Widget State Dumps 📋 PLANNED

Goal: Capture UI hierarchy and state on test failures
Time Estimate: 30-45 minutes
Status: Specification phase

Implementation Plan

Step 1: Create Widget State Capture Utility (30 minutes)

File: src/app/core/widget_state_capture.h (new file)

#ifndef YAZE_CORE_WIDGET_STATE_CAPTURE_H
#define YAZE_CORE_WIDGET_STATE_CAPTURE_H

#include <string>
#include "imgui/imgui.h"

namespace yaze {
namespace core {

struct WidgetState {
  std::string focused_window;
  std::string focused_widget;
  std::string hovered_widget;
  std::vector<std::string> visible_windows;
  std::vector<std::string> open_menus;
  std::string active_popup;
};

std::string CaptureWidgetState();
std::string SerializeWidgetStateToJson(const WidgetState& state);

}  // namespace core
}  // namespace yaze

#endif

File: src/app/core/widget_state_capture.cc (new file)

#include "src/app/core/widget_state_capture.h"
#include "absl/strings/str_format.h"
#include "nlohmann/json.hpp"

namespace yaze {
namespace core {

std::string CaptureWidgetState() {
  WidgetState state;
  
  // Capture focused window
  ImGuiWindow* current = ImGui::GetCurrentWindow();
  if (current) {
    state.focused_window = current->Name;
  }
  
  // Capture active widget
  ImGuiID active_id = ImGui::GetActiveID();
  if (active_id != 0) {
    state.focused_widget = absl::StrFormat("ID_%u", active_id);
  }
  
  // Capture hovered widget
  ImGuiID hovered_id = ImGui::GetHoveredID();
  if (hovered_id != 0) {
    state.hovered_widget = absl::StrFormat("ID_%u", hovered_id);
  }
  
  // Traverse window list
  ImGuiContext* ctx = ImGui::GetCurrentContext();
  for (ImGuiWindow* window : ctx->Windows) {
    if (window->Active && !window->Hidden) {
      state.visible_windows.push_back(window->Name);
    }
  }
  
  return SerializeWidgetStateToJson(state);
}

std::string SerializeWidgetStateToJson(const WidgetState& state) {
  nlohmann::json j;
  j["focused_window"] = state.focused_window;
  j["focused_widget"] = state.focused_widget;
  j["hovered_widget"] = state.hovered_widget;
  j["visible_windows"] = state.visible_windows;
  j["open_menus"] = state.open_menus;
  j["active_popup"] = state.active_popup;
  return j.dump(2);  // Pretty print with indent
}

}  // namespace core
}  // namespace yaze

Step 2: Integrate with TestManager (15 minutes)

Update CaptureFailureContext() in test_manager.cc:

void TestManager::CaptureFailureContext(const std::string& test_id) {
  auto& history_entry = test_history_[test_id];
  
  // 1. Screenshot (IT-08b)
  // ... existing code ...
  
  // 2. Widget state (IT-08c)
  history_entry.widget_state = core::CaptureWidgetState();
  
  // 3. Execution context
  // ... existing code ...
}

Output Example

{
  "focused_window": "Overworld Editor",
  "focused_widget": "ID_12345",
  "hovered_widget": "ID_67890",
  "visible_windows": [
    "Main Window",
    "Overworld Editor",
    "Palette Editor"
  ],
  "open_menus": [],
  "active_popup": ""
}

IT-08d: Error Envelope Standardization 📋 PLANNED

Goal: Unified error format across z3ed, TestManager, EditorManager
Time Estimate: 1-2 hours
Status: Design phase

Proposed Error Envelope

// Shared error structure
struct ErrorContext {
  absl::Status status;
  std::string component;  // "TestHarness", "EditorManager", "z3ed"
  std::string operation;  // "Click", "LoadROM", "RunTest"
  std::map<std::string, std::string> metadata;
  std::vector<std::string> artifact_paths;  // Screenshots, logs, etc.
  std::string actionable_hint;  // User-facing suggestion
};

Integration Points

  1. TestManager: Wrap failures in ErrorContext
  2. EditorManager: Use ErrorContext for all operations
  3. z3ed CLI: Parse ErrorContext and format for display
  4. ProposalDrawer: Display ErrorContext in GUI modal

IT-08e: CLI Error Improvements 📋 PLANNED

Goal: Rich error output in z3ed CLI
Time Estimate: 1 hour
Status: Design phase

Enhanced CLI Output

$ z3ed agent test --prompt "Open Overworld editor"

❌ Test Failed: grpc_click_1696357200
   Component: ImGuiTestHarness
   Operation: Click widget "Overworld"
   
   Error: Widget not found
   
   Artifacts:
   • Screenshot: /tmp/yaze_test_grpc_click_1696357200_failure.bmp
   • Widget State: /tmp/yaze_test_grpc_click_1696357200_state.json
   • Logs: /tmp/yaze_test_grpc_click_1696357200.log
   
   Context:
   • Visible Windows: Main Window, Debug
   • Focused Window: Main Window
   • Active Widget: None
   
   Suggestion:
   → Check if ROM is loaded (File → Open ROM)
   → Verify Overworld editor button is visible
   → Use 'z3ed agent gui discover' to list available widgets

Progress Tracking

Completed

  • IT-08a: Screenshot RPC (1.5 hours)
  • IT-08b: Auto-capture on failure (1.5 hours)
  • IT-08c: Widget state dumps (45 minutes)

In Progress 🔄

  • None - Core error reporting complete

Planned 📋

  • IT-08d: Error envelope standardization (optional enhancement)
  • IT-08e: CLI error improvements (optional enhancement)

Time Investment

  • Spent: 3.75 hours (IT-08a + IT-08b + IT-08c)
  • Remaining: 0 hours for core phases
  • Total: 3.75 hours vs 5-7 hours estimated (under budget )

Next Steps

IT-08 Core Complete

All three core phases of IT-08 (Enhanced Error Reporting) are now complete:

  1. Screenshot capture via SDL
  2. Auto-capture on test failure
  3. Widget state dumps

Optional Enhancements (IT-08d/e - not blocking):

  • Error envelope standardization across services
  • CLI error output improvements
  • HTML error report generation

Recommended Next Priority: IT-09 (CI/CD Integration) or IT-06 (Widget Discovery API)


References


Last Updated: October 2, 2025
Current Phase: IT-08b (Auto-capture on failure)
Overall Progress: 33% Complete (1 of 3 core phases)


Report Generated: October 2, 2025
Author: GitHub Copilot (AI Assistant)
Project: YAZE - Yet Another Zelda3 Editor
Component: z3ed CLI Tool - Test Automation Harness