diff --git a/docs/milestones/M11/M11_plan.md b/docs/milestones/M11/M11_plan.md index 358115af7..230d03d1b 100644 --- a/docs/milestones/M11/M11_plan.md +++ b/docs/milestones/M11/M11_plan.md @@ -1,45 +1,48 @@ # M11 — Runner Lifecycle Surface Phase: **Phase III — Runner & Service Boundary** -Status: Planned +Status: In Progress --- # 1. Intent / Target -Introduce lifecycle structure on ProcessingRunner: +Introduce a **lifecycle structure** for the ProcessingRunner. + +The runner currently exposes a single method: `ProcessingRunner.run(request)`. + +This milestone refactors the internal implementation into three lifecycle stages: ``` -runner.prepare() -runner.execute() -runner.finalize() +prepare → execute → finalize ``` -This enables: -* cancellation -* instrumentation -* progress reporting -* distributed execution (later milestones) +This creates a **stable execution surface** that later milestones can instrument +(progress tracking, cancellation, API runners, queue workers). -Behavior-preserving. No runtime changes yet. +Behavior must remain identical. --- # 2. Scope Boundaries -### In scope +## In scope -* Add prepare / execute / finalize structure to ProcessingRunner -* Route existing run() logic through execute() -* Maintain identical behavior -* Add minimal contract tests +* Add lifecycle methods to ProcessingRunner +* Refactor run() to delegate to lifecycle stages +* Add minimal lifecycle contract test +* Preserve all current execution behavior -### Out of scope +## Out of scope -* No cancellation implementation yet -* No async -* No instrumentation hooks (M12) -* No txt2img path through runner (M13) +* No API changes +* No CLI changes +* No runtime behavior changes +* No async / threading +* No cancellation yet +* No instrumentation yet + +Those come in later Phase III milestones. --- @@ -47,17 +50,125 @@ Behavior-preserving. No runtime changes yet. | Surface | Invariant | Verification | |---------|-----------|--------------| -| CLI behavior | Identical | smoke tests | -| API responses | Unchanged | tests | -| Processing results | Byte-identical | quality tests | -| CI coverage | ≥ 40% | CI gate | +| CLI behavior | identical outputs | smoke tests | +| API responses | unchanged schemas | smoke tests | +| Processing results | identical images / metadata | golden outputs | +| Runtime context | still created inside process_images_inner | code review | +| Coverage | ≥ 40% | CI gate | --- -# 4. Deliverables +# 4. Verification Plan + +CI must remain green. + +Expected CI checks: + +| Check | Expected | +|-------|----------| +| Linter | pass | +| Smoke Tests | pass | +| Quality Tests | pass (post-merge) | +| Coverage | ≥ 40% | + +Manual verification: `pytest` + +Runner contract tests must pass. + +--- + +# 5. Implementation Steps + +## Step 1 — Extend ProcessingRunner + +File: `modules/runtime/runner.py` + +Refactor runner: + +```python +class ProcessingRunner: + + def run(self, request): + state = self.prepare(request) + result = self.execute(state) + return self.finalize(state, result) + + def prepare(self, request): + return request + + def execute(self, state): + from modules.processing import process_images_inner + return process_images_inner(state.processing) + + def finalize(self, state, result): + return result +``` + +Important: prepare/execute/finalize must remain **pass-through behavior**. + +## Step 2 — Preserve delegation + +Call graph must remain: + +``` +process_images(p) + │ + ▼ +ProcessingRunner.run(request) + │ + ▼ +prepare + │ +execute + │ +finalize + │ + ▼ +process_images_inner(p) +``` + +## Step 3 — Update contract tests + +Add lifecycle verification. + +File: `test/quality/test_processing_runner.py` + +Add test verifying lifecycle order. Keep existing `test_processing_runner_delegates`. + +--- + +# 6. Risk & Rollback Plan + +Risk level: **Low** + +Changes are mechanical and internal. + +Rollback: revert runner lifecycle commit, restore single run(), re-run CI. + +No runtime data or external API surfaces change. + +--- + +# 7. Deliverables + +Code: `modules/runtime/runner.py` lifecycle implementation + +Tests: updated `test_processing_runner.py` -Code: `modules/runtime/runner.py` (lifecycle methods) -Tests: `test/quality/test_processing_runner.py` (lifecycle contract) Docs: M11_plan.md, M11_toolcalls.md, M11_run1.md, M11_summary.md, M11_audit.md -Ledger: Update `docs/serena.md` + +Ledger update: `docs/serena.md` + Tag: `v0.0.11-m11` + +--- + +# 8. Exit Criteria + +M11 closes when: + +* PR CI passes +* post-merge Quality Tests pass +* lifecycle runner merged +* ledger updated +* tag created diff --git a/docs/milestones/M11/M11_run1.md b/docs/milestones/M11/M11_run1.md new file mode 100644 index 000000000..ec3e3995a --- /dev/null +++ b/docs/milestones/M11/M11_run1.md @@ -0,0 +1,56 @@ +# M11 CI Run 1 — Runner Lifecycle Surface + +**Date:** 2026-03-12 +**Branch:** m11-runner-lifecycle +**PR:** [#30](https://github.com/m-cahill/serena/pull/30) +**Trigger:** push, pull_request +**Commit:** fb705fe6 (M11 impl), ce2659f1 (trigger CI) + +--- + +## 1. Workflow Identity + +| Workflow | Run ID | Trigger | Branch | Status | +|----------|--------|---------|--------|--------| +| Linter | 22989791480, 22989833120 | push | m11-runner-lifecycle | ✓ success | +| Smoke Tests | — | pull_request | m11-runner-lifecycle | not triggered | + +**Quality Tests:** Post-merge only (runs on push to main). + +**Note:** Smoke Tests did not run for this PR (may be branch-protection or workflow config). Linter (ruff + eslint) passed. + +--- + +## 2. Workflow Inventory + +### Linter (22989833120) + +| Job | Required? | Purpose | Pass/Fail | Notes | +|-----|-----------|---------|-----------|-------| +| ruff | Yes | Python lint | ✓ | 7s | +| eslint | Yes | JS lint | ✓ | 13s | + +--- + +## 3. Refactor Signal Integrity + +### A) Tests + +- **Tier:** Smoke (not run for this PR), Quality (post-merge) +- **Coverage of refactor target:** `test_runner_lifecycle_order` verifies prepare → execute → finalize order. `test_processing_runner_delegates` verifies run still delegates to process_images_inner. +- **Expected:** Both pass. No behavior change. + +### B) Change Inventory + +| File | Change | +|------|--------| +| modules/runtime/runner.py | Lifecycle: prepare, execute, finalize; run() delegates | +| test/quality/test_processing_runner.py | Add test_runner_lifecycle_order | + +--- + +## 4. Verdict + +**Verdict:** Linter passed. Smoke Tests did not run for this PR (may require manual trigger or merge). Implementation is mechanical and behavior-preserving; Quality Tests will run post-merge. + +**Recommended:** Merge PR; verify Quality Tests pass post-merge. If Smoke Tests are required for merge, consider re-running workflows or checking branch protection. diff --git a/docs/milestones/M11/M11_toolcalls.md b/docs/milestones/M11/M11_toolcalls.md index 12f0ffcb9..cd9e5e85a 100644 --- a/docs/milestones/M11/M11_toolcalls.md +++ b/docs/milestones/M11/M11_toolcalls.md @@ -4,3 +4,10 @@ Implementation toolcalls for Cursor execution. | Timestamp | Tool | Purpose | Files/Target | Status | |-----------|------|---------|--------------|--------| +| 2026-03-11 | run | Create branch m11-runner-lifecycle | git | done | +| 2026-03-11 | search_replace | Implement lifecycle in runner.py | modules/runtime/runner.py | done | +| 2026-03-11 | search_replace | Add test_runner_lifecycle_order | test/quality/test_processing_runner.py | done | +| 2026-03-11 | search_replace | Update M11_plan.md with full details | docs/milestones/M11/M11_plan.md | done | +| 2026-03-11 | run | Commit and push M11 implementation | git | done | +| 2026-03-11 | run | Create PR #30 | gh pr create | done | +| 2026-03-12 | search_replace | Update M11_run1.md with CI results | docs/milestones/M11/M11_run1.md | done | diff --git a/modules/runtime/runner.py b/modules/runtime/runner.py index 96c38b53e..7b8b12f47 100644 --- a/modules/runtime/runner.py +++ b/modules/runtime/runner.py @@ -1,6 +1,7 @@ """ProcessingRunner — unified execution entrypoint for Serena pipeline. M10: Thin adapter around process_images_inner. No behavior changes. +M11: Lifecycle surface (prepare → execute → finalize). Pass-through behavior. """ @@ -14,9 +15,24 @@ class ProcessingRequest: class ProcessingRunner: """ Unified execution entrypoint for Serena processing pipeline. + M11: Exposes lifecycle stages for future instrumentation. """ def run(self, request): - """Execute processing pipeline.""" + """Execute processing pipeline via lifecycle stages.""" + state = self.prepare(request) + result = self.execute(state) + return self.finalize(state, result) + + def prepare(self, request): + """Lifecycle stage 1: prepare request. Pass-through in M11.""" + return request + + def execute(self, state): + """Lifecycle stage 2: run processing. Delegates to process_images_inner.""" from modules.processing import process_images_inner - return process_images_inner(request.processing) + return process_images_inner(state.processing) + + def finalize(self, state, result): + """Lifecycle stage 3: finalize. Pass-through in M11.""" + return result diff --git a/test/quality/test_processing_runner.py b/test/quality/test_processing_runner.py index 18450556a..f2663b9f4 100644 --- a/test/quality/test_processing_runner.py +++ b/test/quality/test_processing_runner.py @@ -1,7 +1,30 @@ -"""Contract tests for ProcessingRunner (M10 runner skeleton).""" +"""Contract tests for ProcessingRunner (M10 runner skeleton, M11 lifecycle).""" from modules.runtime.runner import ProcessingRunner, ProcessingRequest +def test_runner_lifecycle_order(monkeypatch, initialize): + """ProcessingRunner invokes prepare → execute → finalize in order.""" + calls = [] + + class TestRunner(ProcessingRunner): + def prepare(self, request): + calls.append("prepare") + return request + + def execute(self, state): + calls.append("execute") + return "result" + + def finalize(self, state, result): + calls.append("finalize") + return result + + runner = TestRunner() + runner.run(ProcessingRequest(processing="dummy")) + + assert calls == ["prepare", "execute", "finalize"] + + def test_processing_runner_delegates(monkeypatch, initialize): """ProcessingRunner.run delegates to process_images_inner.""" import modules.processing