Files
T
2026-07-06 23:52:53 +08:00

55 lines
5.9 KiB
Markdown

## 1. Split `core/` into `driver/` and `device/`
- [x] 1.1 `git mv core/driver.py driver/base.py`, add `driver/__init__.py`, update its internal imports if any
- [x] 1.2 `git mv core/wda_driver.py driver/wda_driver.py`, update its import of `core.driver``driver.base`
- [x] 1.3 `git mv core/device_manager.py device/manager.py`, add `device/__init__.py`, update its imports of `core.driver`/`core.errors`/`core.models``driver.base`/`core.errors`/`core.models`
- [x] 1.4 Confirm `core/__init__.py`, `core/models.py`, `core/errors.py` remain in place unchanged (shared domain types only)
## 2. Rename `vision/` to `perception/`
- [x] 2.1 `git mv vision perception` (carries `ocr.py`, `ui_parser.py`, `scene_builder.py`, `icon_detector.py`, `__init__.py`)
- [x] 2.2 Update internal imports within the renamed package if any reference `vision.*`
## 3. Introduce the `PerceptionProvider` port
- [x] 3.1 Create `perception/provider.py` with a `PerceptionProvider` ABC (`build_scene(screenshot, tree) -> Scene`)
- [x] 3.2 Add a default provider that wraps the existing `scene_builder.py` fusion logic unmodified (same inputs, same `Scene` output — no behavior change)
- [x] 3.3 Add `NullPerceptionProvider` returning an empty `Scene` (correct `width`/`height`, zero elements), usable without any OCR dependency installed
- [x] 3.4 Point `tools/describe_screen.py` (and any other caller of `scene_builder` directly) at the `PerceptionProvider` port instead of importing `scene_builder` directly
- [x] 3.5 Confirm `tests/test_scene_builder.py` still passes unchanged against the default provider
## 4. Relocate the Driver Registry
- [x] 4.1 Create `driver/registry.py`; move `SUPPORTED_DRIVER_TYPES`, `DriverFactoryBuilder`, `build_wda_driver_factory`, and `build_driver_factory` out of `api/console.py` into it, importing `WDADriver`/`WDADriverConfig` from `driver.wda_driver` and `DriverFactory` from `device.manager`
- [x] 4.2 Update `api/console.py` to import `build_driver_factory` (and `SUPPORTED_DRIVER_TYPES` if referenced) from `driver.registry` instead of defining them locally
- [x] 4.3 Update `tests/test_console_api.py` (and any other test importing these names from `api.console`) to import from `driver.registry` where appropriate
## 5. Rename the shared error base
- [x] 5.1 In `core/errors.py`, rename `ApexAgentError``DeviceRuntimeError` (subclasses `DriverError`, `DeviceNotFoundError`, `DeviceOfflineError`, `DeviceBusyError`, `ElementNotFoundError`, `TaskFailedError` keep their names, just re-parented)
- [x] 5.2 Update every `ApexAgentError` reference across `api/`, `tools/`, `runtime/`, `core/`, `driver/`, `device/`, `perception/`, and `tests/` to `DeviceRuntimeError`
## 6. Fix up all import sites and re-point package config
- [x] 6.1 Grep the full tree for `core.driver`, `core.device_manager`, `core.wda_driver`, and `vision.` and update every remaining import (spans `tools/`, `runtime/`, `storage/`, `api/`, `tests/`) to the new `driver.*`/`device.*`/`perception.*` paths
- [x] 6.2 Update `pyproject.toml`: `[tool.setuptools.packages.find].include` to list `driver*`, `device*`, `perception*` alongside the existing `api*`, `core*`, `runtime*`, `storage*`, `tools*`
- [x] 6.3 Run the full `pytest` suite and fix any remaining import errors until it is fully green with no test-logic changes
## 7. Rebrand project identity
- [x] 7.1 Update `pyproject.toml`: `name = "device-agent-runtime"`, add a one-line `description` reflecting the new positioning
- [x] 7.2 Create root `README.md`: project positioning as a device-agnostic Device Agent Runtime (iPhone/WDA as the first driver), link to `docs/ROADMAP.md` and `docs/CONSTITUTION.md`
## 8. Planning artifacts
- [x] 8.1 Create `docs/ROADMAP.md` with the Milestone 0–10 sequence, the three delivery phases, and the long-term "DeviceOS" / Universal Device Runtime direction (v2.0, explicitly not started); explicitly map Milestones 1–4 to already-implemented `apex-agent-mvp` capabilities (`device-management`, `scene-perception`, `agent-runtime`, `task-memory`) rather than treating them as separate future work
- [x] 8.2 Create `docs/adr/0001-device-agnostic-runtime.md` recording this repositioning decision (context, decision, alternatives considered, consequences), referencing this change's design.md decisions
- [x] 8.3 Create `docs/adr/0002-layered-hexagonal-architecture.md` recording the Hexagonal/Ports-and-Adapters + DDD layering decision (D7): dependency direction (`core` domain has zero framework/LLM/HTTP deps; `driver`/`device` adapt external SDKs; `tools` is the capability/port layer; `perception` sits behind `PerceptionProvider`; `runtime` is the application layer where an LLM first enters via the Planner; `api` is the outermost transport adapter) and the bottom-up build order future milestones must respect
- [x] 8.4 Create `docs/CONSTITUTION.md` capturing durable invariants: `Driver` is the only device-capability contract; `tools/` only calls into device/driver capabilities, never a concrete driver; `Scene` is the only perception artifact the LLM ever sees, produced through `PerceptionProvider`; drivers are stateless; Planner produces a plan, Executor is the only thing that calls tools and retries; **no LLM, HTTP, or MCP dependency may appear in `core`, `driver`, `device`, or `tools`** — those enter only at `runtime` (Planner) and `api` respectively; every future milestone change must state in its design.md how it upholds this boundary
- [x] 8.5 Create `research/001-scene-model/README.md` through `research/007-ui-understanding/README.md` (scene-model, world-model, skill, agent, memory, planner, ui-understanding), each a short placeholder stating the track's purpose and that it holds papers/experiments/benchmarks, not code
## 9. Final verification
- [x] 9.1 Run `pytest` once more after all doc additions to confirm nothing in `tests/` was accidentally affected
- [x] 9.2 Manually skim every touched file's diff to confirm no behavior changed — only paths, names, new port, and net-new docs