diff --git a/conductor/tracks/test_harness_hardening_20260310/index.md b/conductor/tracks/test_harness_hardening_20260310/index.md new file mode 100644 index 0000000..6e8bffe --- /dev/null +++ b/conductor/tracks/test_harness_hardening_20260310/index.md @@ -0,0 +1,5 @@ +# Track test_harness_hardening_20260310 Context + +- [Specification](./spec.md) +- [Implementation Plan](./plan.md) +- [Metadata](./metadata.json) diff --git a/conductor/tracks/test_harness_hardening_20260310/metadata.json b/conductor/tracks/test_harness_hardening_20260310/metadata.json new file mode 100644 index 0000000..7fdf148 --- /dev/null +++ b/conductor/tracks/test_harness_hardening_20260310/metadata.json @@ -0,0 +1,8 @@ +{ + "track_id": "test_harness_hardening_20260310", + "type": "chore", + "status": "new", + "created_at": "2026-03-10T00:15:00Z", + "updated_at": "2026-03-10T00:15:00Z", + "description": "Hardening the Hook API and test harness to resolve port conflicts and state serialization issues." +} diff --git a/conductor/tracks/test_harness_hardening_20260310/plan.md b/conductor/tracks/test_harness_hardening_20260310/plan.md new file mode 100644 index 0000000..daad0d2 --- /dev/null +++ b/conductor/tracks/test_harness_hardening_20260310/plan.md @@ -0,0 +1,24 @@ +# Implementation Plan: Hook API & Test Harness Hardening + +## Phase 1: Dynamic Port Allocation +- [ ] Task: Modify `src/api_hooks.py` to attempt binding to port `8999`. If unsuccessful, iterate up to `9010`. +- [ ] Task: Upon successful binding, write the selected port to a temporary artifact file (e.g., `.mcp_port`). +- [ ] Task: Update the `live_gui` fixture in `tests/conftest.py` to read the assigned port from the artifact file and use it for all `ApiHookClient` requests. +- [ ] Task: Conductor - User Manual Verification 'Phase 1: Dynamic Port Allocation' (Protocol in workflow.md) + +## Phase 2: Graceful Teardown +- [ ] Task: Implement a `/api/shutdown` POST endpoint in `src/api_hooks.py`. +- [ ] Task: Ensure the `/api/shutdown` endpoint correctly signals the `AppController` and `App` to perform a clean exit (e.g., joining threads, writing pending saves). +- [ ] Task: Update the `live_gui` fixture to call `/api/shutdown` during teardown, relying on `taskkill` only as a last resort if the process fails to exit gracefully within a timeout. +- [ ] Task: Conductor - User Manual Verification 'Phase 2: Graceful Teardown' (Protocol in workflow.md) + +## Phase 3: State Serialization Audit +- [ ] Task: Audit `src/app_controller.py` to identify all GUI-related state variables that should be exposed to tests (e.g., `show_windows`, individual window toggles). +- [ ] Task: Update `_gettable_fields` to ensure all necessary state is mapped. +- [ ] Task: Refine `_serialize_for_api` in `src/api_hooks.py` (or introduce lightweight dataclass parsing) to handle complex nested objects predictably. +- [ ] Task: Conductor - User Manual Verification 'Phase 3: State Serialization Audit' (Protocol in workflow.md) + +## Phase 4: Verification +- [ ] Task: Write Tests: Create a concurrency test verifying multiple `live_gui` instances can launch simultaneously without port conflicts. +- [ ] Task: Run the entire test suite to ensure the new dynamic port and graceful shutdown logic has not introduced regressions. +- [ ] Task: Conductor - User Manual Verification 'Phase 4: Verification' (Protocol in workflow.md) diff --git a/conductor/tracks/test_harness_hardening_20260310/spec.md b/conductor/tracks/test_harness_hardening_20260310/spec.md new file mode 100644 index 0000000..0cf7566 --- /dev/null +++ b/conductor/tracks/test_harness_hardening_20260310/spec.md @@ -0,0 +1,32 @@ +# Specification: Hook API & Test Harness Hardening + +## Overview +This track focuses on stabilizing the local development and testing environment by hardening the Hook API and its associated `live_gui` test harness. The goal is to eliminate port conflicts, ensure graceful teardowns, and standardize state serialization, laying the groundwork for a future WebSockets implementation. + +## Functional Requirements +- **Dynamic Port Allocation:** + - The Hook Server (`src/api_hooks.py`) will implement a Sequential Fallback strategy for port binding. + - It will attempt to bind to port `8999`. If `Address already in use` is encountered, it will sequentially try ports up to `9010` until successful. + - The successfully bound port will be written to a temporary artifact file (e.g., `.mcp_port` or similar) so the test harness can discover it. +- **Graceful Teardown:** + - Implement a new `/api/shutdown` POST endpoint in the Hook API. + - When called, this endpoint should safely signal the `AppController` and `App` to initiate a clean shutdown (joining threads, closing files) rather than relying on the OS to forcefully kill the process tree. + - Update the `live_gui` fixture to call this endpoint during the `finally` block before resorting to `taskkill` as a last-resort fallback. +- **State Serialization Audit:** + - Formalize the structure returned by `/api/gui/state`. + - Ensure all fields defined in `_gettable_fields` are safely serialized using standard dataclass/dict traversal (avoiding deep Pydantic dependencies for now, keeping it lightweight but strictly typed for future WebSocket pipeline compatibility). + - Add missing fields discovered during recent UI tracks (e.g., `show_windows` states). + +## Non-Functional Requirements +- **Stability:** The `live_gui` fixture must pass 100% of the time without port conflict errors when tests are run sequentially. +- **Performance:** The port scanning logic should fail fast and bind within milliseconds. + +## Acceptance Criteria +- [ ] A test script can successfully launch two concurrent `live_gui` instances, and they bind to different ports. +- [ ] Calling `/api/shutdown` successfully stops the GUI process and returns a 200 OK. +- [ ] The `live_gui` fixture uses the shutdown endpoint and the test suite passes without leaving orphaned processes. +- [ ] The state returned by `/api/gui/state` is fully documented and includes all relevant nested objects (like `show_windows`). + +## Out of Scope +- Implementing the WebSockets streaming logic (this track only prepares the state schema for it). +- Fixing failing simulation tests that are unrelated to the harness itself.