<!-- task=dispatcher_parallel_limit plan=3 tag=REVIEW_TEST -->

# Replace Vacuous Parallel-Limit Scheduler Evidence

## For the Implementing Agent

> **[IMPLEMENTING AGENT — READ FIRST]** Filling implementation-owned sections in `CODE_REVIEW-*-G??.md` is mandatory. Run every verification command, paste actual notes and output into the review file, keep both active files in place, and report ready for review. Finalization is code-review-skill only. If blocked, record only the exact blocker, attempted commands/output, and resume condition in implementation-owned evidence fields. Do not ask the user, call user-input tools, create control-plane stop files, classify the next state, archive logs, or write `complete.log`.

## Background

The workspace-global capacity and review-preflight implementation passes the current suite, but four explicitly required concurrency scenarios are not exercised by the assertions that claim them. Replace only the non-representative tests with deterministic production-scheduler evidence; the reviewed dispatcher behavior does not currently require another source change.

## Archive Evidence Snapshot

- The current FAIL pair will archive as `agent-task/dispatcher_parallel_limit/plan_cloud_G06_2.log` and `agent-task/dispatcher_parallel_limit/code_review_cloud_G06_2.log`.
- Verdict: FAIL with one Required invariant set and no Suggested or Nit findings.
- Required corrections: measure mixed-role peak activity through `dispatch_with_store`; prove capacity-waiter re-admission without a completion-triggered full scan; exercise dry-run against persisted live occupancy from another task group; and preseed the claim on the task that is actually capacity-deferred.
- Fresh reviewer verification passed 37 focused tests and 300 full tests, but the current assertions do not execute those four named paths.
- All implementation facts are reproduced here. Read the two archived files above only if their exact prior wording is required.

## Analysis

### Files Read

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/rules/common/philosophy.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/testing-smoke.md`
- `agent-ops/skills/project/orchestrate-agent-task-loop/SKILL.md`
- `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`
- `agent-task/dispatcher_parallel_limit/PLAN-cloud-G06.md`
- `agent-task/dispatcher_parallel_limit/CODE_REVIEW-cloud-G06.md`

### SDD Criteria

Not applicable. This is a non-roadmap test-evidence repair and does not complete a Milestone Task.

### Verification Context

- Handoff: the official review supplied the raw Required finding, exact current-pair archive identities, and fresh local command output.
- Environment: local checkout `/config/workspace/iop`, Python standard library only, no credential, network, provider CLI, deployment, or external runtime.
- Fresh repository-native evidence:
  - `python3 -m py_compile agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py` passed.
  - The focused dispatcher command passed 37 tests.
  - Full unittest discovery passed 300 tests.
  - `git diff --check` passed.
- Required constraints: tests must deny real provider execution, use the real state and scheduler seams named by the behavior, and leave no repository-local generated tool or cache artifact as evidence.
- External Verification Preflight: not applicable; every required scenario runs in standard-library temporary workspaces with fake role runners.
- Gap: the suite is green while four planned scheduler oracles are absent.
- Confidence: high; each gap is visible directly in the named test body and has a deterministic replacement oracle.

### Test Coverage Gaps

- Mixed-role peak: `test_limit_two_selects_reviews_before_worker_and_caps_total` calls only `select_dispatch_candidates` and cannot observe concurrent role attempts.
- Cached re-admission: `test_limit_one_serializes_and_re_admits_capacity_waiter` returns a completed archive from every fake worker, allowing a full scan instead of proving the cache-only path.
- Existing claim retention: `test_existing_lifecycle_owner_retains_claim_while_waiting` selects the preclaimed task and never capacity-defers that owner.
- Dry-run global occupancy: `test_dry_run_applies_cap_and_leaves_state_unchanged` creates no persisted other-group live locator, so it cannot prove that dry-run uses workspace-wide occupancy.
- Review-preflight refill, invalid CLI values, default unlimited selection, live filtered occupancy, and provider-deny guards already have direct assertions and remain unchanged.

### Symbol References

None. No production symbol is renamed or removed; test method names may be replaced in the same module.

### Split Judgment

Keep one compact plan. The four regressions are the evidence boundary for one workspace-global admission invariant and share the same temporary-workspace builders, fake role runners, and focused verification command.

### Scope Rationale

Modify only `test_dispatch.py` and the active review evidence. Exclude `dispatch.py`, routing policy, provider selection, workspace liveness semantics, documentation, roadmap state, deployment, and live-provider smoke unless a new deterministic failing test proves a production correction is necessary.

### Final Routing

- `evaluation_mode`: `isolated-reassessment`
- `finalizer`: `finalize-task-policy.sh` (`pair`)
- Build closures: `scope_closed=true`, `context_closed=true`, `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`
- Build scores: scope `1`, state/concurrency `2`, blast/irreversibility `0`, evidence/diagnosis `2`, verification `1`; grade `G06`
- Build base/route: `local-fit` / `recovery-boundary`; lane `cloud`; canonical filename `PLAN-cloud-G06.md`
- Review closures: `scope_closed=true`, `context_closed=true`, `verification_closed=true`, `evidence_trusted=true`, `ownership_closed=true`, `decision_closed=true`
- Review scores: scope `1`, state/concurrency `2`, blast/irreversibility `0`, evidence/diagnosis `2`, verification `1`; grade `G06`
- Review route: `official-review`; lane `cloud`; Codex `gpt-5.6-sol` xhigh; canonical filename `CODE_REVIEW-cloud-G06.md`
- `large_indivisible_context=false`
- Positive loop risks: `temporal_state`, `concurrent_consistency`; count `2`
- Recovery signals: `review_rework_count=2`, `evidence_integrity_failure=true`
- Capability-gap evidence: none.

## Implementation Checklist

- [ ] Replace helper-only peak and archive-driven re-admission checks with deterministic `dispatch_with_store` regressions that measure mixed-role active/peak attempts and prove cache-only waiter admission without another full scan.
- [ ] Add real-state dry-run cross-group occupancy and capacity-deferred existing-claim retention assertions while preserving the class-wide provider-deny guard.
- [ ] Run the focused and full final verification commands and record fresh output.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_TEST-1] Prove mixed-role peak and cache-only re-admission

#### Problem

The test at `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py:11486` stops at selector output, so it cannot prove that concurrent review/worker/self-check attempts stay under the cap. The test at line 11511 returns a completed archive from every fake worker, which triggers the only permitted full-scan path and bypasses the cache-only re-admission behavior named by the test.

#### Solution

Replace both tests with scheduler-level scenarios using fake role coroutines, an `asyncio.Event`, and shared active/peak counters. Persist the minimum valid stage state needed for one review, one worker, and one self-check (or a worker-to-review transition), assert every runner owns a claim at entry, and stop each fake deterministically without invoking a provider. For the cache case, make an ordinary stage transition return without a completed archive, assert the capacity waiter starts from the existing task cache, and assert `scan_tasks` was called only for initial discovery.

Before (`test_dispatch.py:11486-11509`):

```python
def test_limit_two_selects_reviews_before_worker_and_caps_total(self):
    selected, deferred, _ = dispatch.select_dispatch_candidates(
        store, ready, persist=False, available_slots=2,
    )
    self.assertEqual(len(selected), 2)
```

After:

```python
async def fake_role(workspace_path, store_arg, task_arg, *args, **kwargs):
    nonlocal peak
    active.add(task_arg.name)
    peak = max(peak, len(active))
    if len(active) == 2:
        release.set()
    await release.wait()
    self.assertIn(task_arg.name, store_arg.write_claim_snapshot())
    active.remove(task_arg.name)

self.assertLessEqual(peak, 2)
self.assertEqual(scan_tasks.call_count, 1)
```

#### Modified Files and Checklist

- [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`: replace the selector-only mixed-role cap check with an event-gated scheduler regression and active/peak oracle.
- [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`: replace the completed-archive re-admission setup with an ordinary stage transition and assert no additional full scan.

#### Test Strategy

Use existing temporary-workspace task/state helpers and fake `run_worker`, `run_selfcheck`, and `run_review` seams. Assert role start order, claim ownership at entry, peak active attempts at or below the positive limit, the capacity waiter eventually starts, and `scan_tasks.call_count == 1` until no fake returns a completed archive.

#### Verification

```bash
python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py ParallelLimitSchedulingTest
```

Expected: scheduler-level mixed-role and cached re-admission regressions pass, with no real provider command or subprocess.

### [REVIEW_TEST-2] Prove dry-run global occupancy and deferred claim retention

#### Problem

The test at `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py:11580` checks the claim of the task selected again on the second pass, not a preclaimed task deferred by capacity. The dry-run test at line 11612 has no other-group live state, so it passes even if dry-run ignores workspace-global occupancy.

#### Solution

Preseed a lifecycle claim for a disjoint task ordered after the admitted task, then call normal persistent admission with one slot and assert the deferred owner's entire claim record is unchanged. Reuse the real locator/PID state builder from the live cross-group test in a dry-run filtered invocation; snapshot `store.data`, capture the capacity-wait classification, assert no role runner executes, and compare the full in-memory state after dispatch.

Before (`test_dispatch.py:11596-11608`):

```python
ready_second = [
    (tasks[0], "review"),
    (tasks[1], "review"),
]
selected_2, deferred_2, _ = dispatch.select_dispatch_candidates(
    store, ready_second, persist=True, available_slots=1,
)
self.assertEqual(selected_2[0][0].name, "sim/01_task_0")
```

After:

```python
prior_claim = copy.deepcopy(store.write_claim_snapshot()[deferred_owner.name])
selected, deferred, _ = dispatch.select_dispatch_candidates(
    store, [(admitted, "review"), (deferred_owner, "review")],
    persist=True, available_slots=1,
)
self.assertEqual(store.write_claim_snapshot()[deferred_owner.name], prior_claim)
```

#### Modified Files and Checklist

- [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`: arrange for the existing lifecycle claim owner itself to be capacity-deferred and assert its full claim record is retained.
- [ ] `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py`: add persisted other-group live locator evidence to the filtered dry-run case and assert capacity classification, zero runner calls, and byte-for-byte state preservation.

#### Test Strategy

Use one physical temporary workspace with two task groups and a locator under the active `StateStore.runs` root using the current process PID and matching workspace identity. Do not mock `workspace_live_agent_processes`; patch only role runners and shared review setup. Compare a deep copy of `store.data`, the selected/deferred identities, and the preseeded claim record.

#### Verification

```bash
python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py ParallelLimitSchedulingTest WriteSetTest
```

Expected: global dry-run occupancy and deferred lifecycle-claim retention pass without state mutation or provider execution.

## Modified Files Summary

| File | Items |
|---|---|
| `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py` | REVIEW_TEST-1, REVIEW_TEST-2 |
| `agent-task/dispatcher_parallel_limit/CODE_REVIEW-cloud-G06.md` | REVIEW_TEST-1, REVIEW_TEST-2 |

## Final Verification

Run from `/config/workspace/iop`:

```bash
python3 -m py_compile agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py
python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_dispatch.py ParallelLimitSchedulingTest ReviewSchedulingTest WriteSetTest BlockerDrainTest DispatcherConvergenceSimulationTest
python3 -m unittest discover -s agent-ops/skills/project/orchestrate-agent-task-loop/tests -p 'test_*.py'
git diff --check
```

Expected: compilation passes; focused scheduler tests prove mixed-role peak limits, cache-only re-admission, dry-run external occupancy, existing-claim retention, and preflight refill; the complete suite passes fresh; `git diff --check` prints nothing. Python test cache is not accepted.

After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
