# Feature Spec: Reactive Execution Enrollment and Scheduling (AOP)

> **Purpose of this document**: Define the architecture and implementation plan for near-real-time `aop add` enrollment into an already-running supervisor, using a dedicated enrollment component and a pluggable scheduling policy that will later support an organizer agent outside the feature cluster.

**Version:** 1.0  
**Date:** 2026-03-15  
**Status:** Draft  
**Roadmap Mapping:** M50

---

## 0. Standards and Dependencies

### 0.1 Required Standards

All implementation MUST preserve:

- single active run ownership per repository
- deterministic error envelopes and artifact writes
- atomic state mutation through existing kernel/application service paths
- one global orchestrator session and one shared reconciler lane per active run
- existing feature lifecycle invariants and terminal-state rules
- MCP/in-process parity for runtime control requests
- `operation_id` idempotency for mutating tool calls
- coverage thresholds: Lines >=90%, Branches >=90%, Functions >=90%, Statements >=90%

### 0.2 Required Inputs

Implementing agents MUST read:

- `apps/control-plane/src/supervisor/runtime.ts`
- `apps/control-plane/src/supervisor/run-coordinator.ts`
- `apps/control-plane/src/supervisor/session-orchestrator.ts`
- `apps/control-plane/src/supervisor/planning-wave-executor.ts`
- `apps/control-plane/src/supervisor/build-wave-executor.ts`
- `apps/control-plane/src/supervisor/qa-wave-executor.ts`
- `apps/control-plane/src/supervisor/types.ts`
- `apps/control-plane/src/application/services/execution-control-service.ts`
- `apps/control-plane/src/application/services/run-lease-service.ts`
- `apps/control-plane/src/core/kernel.ts`
- `apps/control-plane/src/core/execution-control.ts`
- `apps/control-plane/src/core/runtime-sessions.ts`
- `apps/control-plane/src/core/path-layout.ts`
- `apps/control-plane/src/cli/add-command-handler.ts`
- `apps/control-plane/src/cli/status-command-handler.ts`
- `apps/control-plane/test/execution-control-service.spec.ts`
- `apps/control-plane/test/run-coordinator.spec.ts`
- `apps/control-plane/test/supervisor.spec.ts`
- `spec-files/outstanding/agentic_orchestrator_add_feature_to_active_execution_spec.md`

### 0.3 Scope

This spec implements:

- reactive polling of pending execution requests during a live run
- a dedicated enrollment component outside `SupervisorRuntime` core orchestration logic
- a pluggable scheduling interface for deciding whether newly submitted features should run now, wait, or be deferred
- near-real-time visibility for accepted add requests
- safe integration points for a future organizer agent that determines feature ordering and dependencies

Out of scope:

- multiple active runs in the same repository
- mid-flight provider/model/execution-mode overrides for added features
- a separate long-lived daemon process outside the current supervisor
- direct cluster creation from background threads without coordinator mediation
- dependency graph implementation for the organizer agent itself

### 0.4 Design Guardrails

Implementation MUST follow:

- **KISS**: do not redesign run lease semantics or feature cluster ownership
- **SRP**: polling, scheduling policy, and queue mutation MUST be separate concerns
- **SOLID**:
  - open/closed for future request types and future scheduling policies
  - interface segregation between polling and scheduling contracts
  - dependency inversion so coordinator depends on an enrollment contract, not timer or file details
- **Hexagonal architecture**: runtime control artifact access stays behind services/kernel ports
- **Composition over inheritance**: compose a new enrollment service into supervisor startup/shutdown
- **Single-writer runtime state**: only the coordinator may mutate the live run queue and cluster assignments

---

## 1. Problem Statement

### 1.1 Current Defect

`aop add` now durably writes pending requests into `.aop/runtime/<instanceId>/execution-control.json`, but the live supervisor only checks for pending requests at coarse boundaries in the main coordinator loop.

As a result:

1. a request may remain `pending` for minutes while a long planning/build/QA operation is running
2. the run lease may continue heartbeating, which makes the run appear healthy even though enrollment is not reactive
3. users do not get the expected behavior of “add work to the active execution if there is room”

### 1.2 Architectural Constraint

The solution must not hard-code feature ordering into the polling mechanism because a future organizer agent will exist outside the feature cluster and will decide:

- which enrolled features can start immediately
- which features must wait on other features
- which features should be deprioritized or deferred

That future system must be able to plug into the same enrollment pipeline without replacing the transport or state plumbing.

---

## 2. Design Decision

### 2.1 Chosen Approach

Introduce a dedicated supervisor-side enrollment component, composed into `SupervisorRuntime` but implemented as its own class, with the following responsibilities:

1. poll for pending execution requests on a short interval
2. optionally react to a lightweight wake/signal channel for lower-latency detection
3. normalize them into enrollment candidates
4. pass those candidates through a scheduling policy
5. hand the resulting decisions to `RunCoordinator`, which remains the only mutator of queue and cluster state

### 2.2 Explicit Non-Decision

The new component MUST NOT:

- directly initialize feature clusters
- directly mutate `state.queue`
- directly mark requests applied or rejected
- directly reorder the queue using internal heuristics beyond what the scheduler returns

Those responsibilities remain in `RunCoordinator`.

### 2.3 Why This Design

This approach:

- fixes the current latency defect
- avoids pushing more logic into `SupervisorRuntime`
- preserves a clean seam for a future organizer agent
- keeps runtime state mutation serialized in one place
- preserves durable correctness even if reactive signaling is lost
- avoids making ephemeral pub/sub the sole source of truth

### 2.4 Detection vs Admission

This spec separates two concerns:

- **Detection**: noticing that a new execution request exists
- **Admission**: safely incorporating that request into the active execution

Reactive signaling improves detection latency.

It does **not** eliminate the need for coordinator-controlled admission, because new work may arrive while:

- a build wave is running
- a QA repair loop is in progress
- a feature cluster mutation is in progress

Therefore:

- detection may be event-driven or interval-driven
- admission must remain coordinator-serialized

---

## 3. Architecture Overview

### 3.1 New Components

Add the following supervisor-layer abstractions:

#### A. `ExecutionEnrollmentService`

Primary runtime-owned service responsible for:

- interval-based polling
- optional wake-signal subscription
- request detection
- buffering or signaling newly available enrollment work
- invoking the scheduler
- exposing a safe `drainReadyDecisions()` API to the coordinator

This is the main new class required by this spec.

#### B. `EnrollmentScheduler` interface

Policy interface responsible for classifying enrollment candidates.

Initial implementation:

- `CapacityAwareEnrollmentScheduler`

Future implementation:

- `OrganizerAgentEnrollmentScheduler`

#### C. `EnrollmentDecision`

Value type describing what should happen to each requested feature.

Allowed decisions:

- `queue_now`
- `defer`
- `reject`

### 3.2 Existing Components That Remain Authoritative

#### `SupervisorRuntime`

Remains the composition root only:

- creates and starts `ExecutionEnrollmentService`
- stops it during runtime shutdown
- injects the scheduler implementation
- does not absorb enrollment logic into itself

#### `RunCoordinator`

Remains the execution authority:

- drains ready enrollment decisions
- mutates queue state
- initializes clusters through existing session orchestrator flows
- marks execution requests applied or rejected

#### `ExecutionControlService`

Remains the durable artifact service:

- submit request
- list request
- drain pending request snapshots
- mark processed

This spec does not move file persistence into the supervisor.

---

## 4. New Contracts

### 4.1 `ExecutionEnrollmentService` Contract

The new class should expose methods along these lines:

```ts
interface ExecutionEnrollmentService {
  start(): Promise<void>;
  stop(): Promise<void>;
  notifyNewRequestHint(): Promise<void>;
  noteSafeCheckpoint(): Promise<void>;
  drainReadyDecisions(): Promise<EnrollmentDecisionBatch[]>;
  hasPendingWork(): boolean;
}
```

Required behavior:

- `start()` begins polling on a configured interval
- `stop()` stops the timer and flushes in-flight polling work
- `notifyNewRequestHint()` is a best-effort wake signal; it hints that the service should reconcile immediately, but correctness must not depend on it
- `noteSafeCheckpoint()` allows the coordinator to request immediate reconciliation after a feature-level atomic step completes
- `drainReadyDecisions()` returns scheduler-produced decisions that are ready for coordinator application
- `hasPendingWork()` allows fast-path checks without forcing a file read

### 4.2 `EnrollmentScheduler` Contract

```ts
interface EnrollmentScheduler {
  schedule(input: EnrollmentSchedulingInput): Promise<EnrollmentSchedulingResult>;
}
```

`EnrollmentSchedulingInput` MUST include:

- active feature ids
- queued feature ids
- assigned feature ids from runtime sessions
- current `max_active_features`
- request items and requested features
- optional feature metadata needed for future dependency checks

`EnrollmentSchedulingResult` MUST return per-feature decisions with a machine-readable reason.

### 4.3 `EnrollmentDecision` Shape

```ts
type EnrollmentDecisionDisposition = 'queue_now' | 'defer' | 'reject';

interface EnrollmentDecision {
  request_id: string;
  feature_id: string;
  disposition: EnrollmentDecisionDisposition;
  reason: string;
}
```

Reason values for the initial scheduler MUST be deterministic and finite. At minimum:

- `capacity_available`
- `capacity_full`
- `already_active`
- `already_queued`
- `already_assigned_cluster`
- `terminal_status`
- `dependency_blocked`
- `scheduler_rejected`

`dependency_blocked` is reserved for the future organizer scheduler and SHOULD NOT be emitted by the initial capacity-aware scheduler unless a dependency-aware source is already present.

---

## 5. Execution Lifecycle

### 5.1 Submission

Unchanged from the current `aop add` design:

1. `aop add` resolves or resumes the target feature
2. CLI submits a durable `runtime.execution_request_submit`
3. request is written as `pending`

### 5.2 Detection

The new enrollment service uses a hybrid detection model.

Required baseline:

- `execution_enrollment_poll_interval_ms = 2000`

Polling MUST:

- read only the active run’s request set
- ignore non-pending requests
- debounce duplicate reads of the same pending request set
- avoid marking requests applied or rejected directly

Optional improvement:

- a lightweight in-process or artifact-backed wake signal may call `notifyNewRequestHint()` so the active supervisor does not need to wait for the next interval to notice newly submitted work

Critical rule:

- the durable execution-control artifact remains canonical
- wake signaling is only an optimization
- lost wake signals must not lose requests

### 5.3 Scheduling

For each pending request batch:

1. service gathers current runtime state snapshot
2. service calls the scheduler
3. scheduler returns one decision per requested feature
4. service stores those decisions in an in-memory ready queue for the coordinator

### 5.4 Application

At the next safe coordinator checkpoint:

1. `RunCoordinator` drains ready decisions
2. for `queue_now`:
   - call existing feature initialization path if needed
   - append feature to the run queue
   - rebalance immediately if active capacity exists
3. for `defer`:
   - keep the execution request `pending`
   - do not lose the decision context
4. for `reject`:
   - mark the feature rejected in the request outcome

### 5.5 Wave Routing After Enrollment

Enrollment does not imply “start planning.”

Once a feature has been admitted and promoted to active, the coordinator MUST route it by its persisted feature status, using the existing wave executors as the source of truth.

Required behavior:

- a feature in `planning` enters the planning wave
- a feature in `building` enters the build wave
- a feature in `qa` enters the QA wave
- a feature in `ready_to_merge` does not re-enter planning/build/QA and should follow existing post-QA/merge handling
- a feature in `blocked` does not automatically enter a worker wave unless existing blocked-feature recovery logic transitions it back to an executable phase

This means the scheduler never decides which wave to run. It only decides whether the feature can be admitted into the active execution. The wave executor selection remains status-driven inside the coordinator loop.

### 5.6 Checkpoint Mini-Pass Dispatch

The coordinator MUST NOT wait for a full top-level iteration boundary if newly admitted work targets an earlier wave than the wave currently in progress.

Example:

- current execution is in `buildWaveExecutor`
- a newly admitted feature has persisted status `planning`

Correct behavior:

1. detect the new request immediately or on the next poll
2. wait for the next safe checkpoint in the current build work
3. admit/promote the feature through the coordinator
4. schedule a planning mini-pass before that feature is ever considered for build

Required rule:

- if admitted work targets a phase earlier than the current phase cursor, the coordinator should run a checkpoint mini-pass for the earlier applicable wave at the next safe boundary

This avoids unnecessary full-loop latency while preserving deterministic wave ordering.

Mini-pass constraints:

- mini-passes must operate on the current active feature set
- mini-passes must remain status-driven
- mini-passes must not interrupt an in-flight worker/provider operation
- mini-passes must be coordinator-invoked only

### 5.7 Completion

An execution request may only be marked:

- `applied` when every requested feature has either been queued or deterministically skipped for a stable reason
- `rejected` when the entire request fails for a request-level error

If any requested feature remains deferred because of scheduling policy, the request MUST remain `pending`.

This is important for future organizer-agent compatibility: a feature blocked on another feature should remain visible as outstanding work, not disappear into a processed tombstone.

### 5.8 Retry Semantics

This spec MUST explicitly preserve two distinct retry mechanisms.

#### A. Inline gate-repair retries during active execution

Existing build/QA retry behavior remains unchanged:

- build-wave gate retries continue to execute inside `BuildWaveExecutor`
- QA-wave gate retries continue to execute inside `QaWaveExecutor`
- these retries do not go through the enrollment service

Reason:

- they are part of a feature already active in the current run
- they are local repair loops, not admission of new work into the run

#### B. Explicit `aop retry` for non-active or blocked features

Explicit retry must become compatible with the single-active-execution model.

Required behavior:

1. `aop retry` may still reset retry counters and patch feature status exactly as it does today.
2. If there is no active run, retry may continue to use the existing resume path.
3. If there is an active run for the repository, retry MUST NOT try to start a second supervisor.
4. Instead, after the retry state mutation/gate action completes, the feature MUST be re-enrolled through the same execution-enrollment pipeline used by `aop add --resume`.

Wave re-entry after retry MUST remain status-driven:

- forced or recovered retry targeting `building` re-enters the build wave
- forced or recovered retry targeting `qa` re-enters the QA wave
- retry that leaves the feature `blocked` does not re-enter a worker wave until blocked recovery or a subsequent explicit action changes its state

This ensures retry is a state-transition concern first and an enrollment concern second.

The enrollment service must not invent special retry-only execution paths.

---

## 6. Safe-Checkpoint Model

### 6.1 Required Checkpoints

The coordinator MUST call into the enrollment service at these safe points:

- before the initial rebalance
- after each feature cluster close
- after each per-feature planner decision
- after each per-feature builder decision
- after each per-feature QA decision
- after each gate run
- after each top-level planning/build/QA wave
- before runtime shutdown

These checkpoints are also the only legal places to trigger a checkpoint mini-pass.

### 6.2 Safety Rule

“Safe checkpoint” means:

- no queue mutation is currently in progress
- no cluster assignment mutation is currently in progress
- a single feature-level unit of work has just completed

The implementation MUST NOT preempt or cancel an in-flight worker operation solely to apply enrollment.

### 6.3 Responsiveness Target

This spec does not guarantee cluster creation in the middle of a long provider call.

It does require:

- request detection within one poll interval, or faster if a wake hint is delivered
- request visibility in logs/status immediately after detection
- queue application at the next safe checkpoint
- wave dispatch at the next safe checkpoint, including a mini-pass when newly admitted work targets an earlier phase than the current phase cursor

This is the correct consistency/performance tradeoff for the current architecture.

---

## 7. Default Scheduling Policy

### 7.1 Initial Scheduler: `CapacityAwareEnrollmentScheduler`

The first scheduler implementation MUST be intentionally simple:

- if feature is already active: `reject` with `already_active`
- if feature is already queued: `reject` with `already_queued`
- if feature is already assigned in runtime sessions: `reject` with `already_assigned_cluster`
- if feature is terminal: `reject` with `terminal_status`
- otherwise:
  - if active capacity is available or the queue is allowed to grow: `queue_now`
  - if policy explicitly wants deferred behavior when queue growth should be organizer-controlled: `defer` with `capacity_full`

Recommended initial behavior:

- allow queue growth under capacity pressure
- use `defer` only when future organizer behavior is explicitly enabled or when dependency metadata blocks it

### 7.2 Organizer-Agent Compatibility

The future organizer agent should plug in by implementing `EnrollmentScheduler`.

That scheduler may:

- inspect dependency metadata
- rank features
- declare a feature blocked until another feature reaches a required state
- allow only certain features to enter the queue

The poller and coordinator MUST NOT need redesign for that future swap.

### 7.3 Policy Separation

Do not encode organizer behavior into:

- `ExecutionEnrollmentService`
- `SupervisorRuntime`
- `ExecutionControlService`

Only the scheduler should decide ordering/dependency outcomes.

### 7.4 Retry Is Not Scheduling Policy

Retry eligibility, gate retry counters, and blocked-feature recovery MUST remain outside the scheduler abstraction.

The scheduler may observe feature status and decide whether a feature can be admitted, but it MUST NOT:

- increment or reset `gate_retry_count`
- infer repair prompts
- run gates directly
- replace blocked-feature recovery

Those remain existing execution concerns owned by the CLI retry flow, run coordinator, and wave executors.

---

## 8. Runtime Artifacts and Status Projection

### 8.1 Execution Request Artifact

The existing `.aop/runtime/<instanceId>/execution-control.json` artifact remains canonical.

This spec adds meaning to `pending`:

- `pending` may now mean “not yet detected” or “detected but deferred by scheduler”

### 8.2 Optional In-Memory Only State

The enrollment service may keep transient in-memory state such as:

- last observed pending request fingerprint
- ready decisions awaiting coordinator application
- deferred decisions with timestamps

This state MUST be reconstructible from durable artifacts and live runtime state after process restart.

### 8.3 Status Output Requirements

`aop status` and dashboard projections SHOULD be updated to distinguish:

- `pending_unseen`
- `pending_deferred`
- `applied`
- `rejected`

If adding new outward-facing states is too disruptive for this milestone, status MUST at minimum include:

- that the request is still pending
- whether the supervisor has detected it
- whether the scheduler deferred it and why

---

## 9. Logging and Observability

### 9.1 Required Runtime Events

Add structured runtime events for:

- execution request detected
- execution request wake hint received
- scheduler evaluated request
- feature queued from request
- feature deferred from request
- checkpoint mini-pass scheduled
- checkpoint mini-pass executed
- request applied
- request rejected

### 9.2 Logging Requirements

When a request is detected, the active CLI session SHOULD emit a concise log line such as:

```text
[enrollment] detected request exec_req_123 for feature_a
```

When a feature is deferred:

```text
[enrollment] deferred feature_a: capacity_full
```

When a feature is queued:

```text
[enrollment] queued feature_a from request exec_req_123
```

This addresses the current operator blind spot.

---

## 10. Failure Handling

### 10.1 Polling Failure

If polling the execution-control artifact fails:

- supervisor should log the failure
- enrollment polling should retry on the next interval
- the run should not fail unless the failure indicates a corrupted invariant or unrecoverable schema error

### 10.2 Scheduler Failure

If the scheduler throws:

- the request MUST remain `pending`
- the failure should be logged with request id and feature ids
- the supervisor should continue running

If wake signaling fails or is dropped:

- the request must still be detected by baseline polling
- no request may depend solely on pub/sub delivery for correctness

### 10.3 Coordinator Application Failure

If coordinator application fails for a specific feature:

- the request MUST remain `pending` unless a deterministic reject outcome can be recorded safely
- partial application MUST be represented explicitly in the request outcome
- duplicate queue insertion MUST remain impossible

### 10.4 Restart Behavior

After supervisor restart:

- pending requests MUST still be visible from the artifact
- deferred work MUST be re-evaluated by the scheduler
- no orphan in-memory decision state may be required for correctness

---

## 11. Files To Add or Modify

### 11.1 New Files

- `apps/control-plane/src/supervisor/execution-enrollment-service.ts`
- `apps/control-plane/test/execution-enrollment-service.spec.ts`

### 11.2 Likely Modified Files

- `apps/control-plane/src/supervisor/runtime.ts`
- `apps/control-plane/src/supervisor/run-coordinator.ts`
- `apps/control-plane/src/supervisor/types.ts`
- `apps/control-plane/src/application/services/execution-control-service.ts`
- `apps/control-plane/src/cli/status-command-handler.ts`
- `apps/control-plane/test/run-coordinator.spec.ts`
- `apps/control-plane/test/supervisor.spec.ts`
- `apps/control-plane/test/cli.unit.spec.ts`

### 11.3 Optional but Recommended Files

- `apps/control-plane/src/application/services/reporting-service.ts`
- dashboard-related status projection utilities if they surface execution request state

---

## 12. Milestones

### M50.1 — Introduce `ExecutionEnrollmentService`

Create a dedicated supervisor component that:

- owns timer lifecycle
- optionally accepts wake hints
- polls pending execution requests
- buffers ready scheduling decisions
- exposes a coordinator-facing drain API

### M50.2 — Add Hybrid Detection

Add best-effort reactive wake signaling on top of durable polling, without making signaling the sole source of truth.

### M50.3 — Add Scheduler Abstraction

Create `EnrollmentScheduler` and default `CapacityAwareEnrollmentScheduler`.

Acceptance:

- no scheduling policy lives inside `SupervisorRuntime`
- future organizer-agent-backed implementation can be added without changing poller transport

### M50.4 — Coordinator Safe Checkpoints

Refactor `RunCoordinator` to call the enrollment service at safe checkpoints and apply ready decisions through coordinator-owned queue mutation.

### M50.5 — Checkpoint Mini-Pass Dispatch

Teach the coordinator to run the appropriate earlier-wave mini-pass at the next safe checkpoint when newly admitted work would otherwise wait for a full loop cycle.

### M50.6 — Request Outcome Semantics for Deferred Work

Adjust request processing semantics so deferred features keep the request pending rather than being prematurely marked applied.

### M50.7 — Logging and Status Visibility

Emit structured enrollment logs and surface deferred/pending/applied state in status output.

### M50.8 — Status-Driven Wave Routing

Make the spec- and test-level contract explicit that admitted features re-enter the matching wave by persisted status, including `--resume` and retry-driven re-entry.

### M50.9 — Retry Compatibility with Active Execution

Ensure explicit retry can re-enroll into the active execution instead of attempting to create a second supervisor run when a fresh run lease already exists.

### M50.10 — Restart and Recovery Semantics

Ensure pending/deferred requests are re-evaluated after restart with no reliance on transient state.

### M50.11 — Organizer-Agent Extension Seam

Document and test the scheduler substitution point for a future organizer-agent implementation.

---

## 13. Acceptance Criteria

Implementation is complete when all of the following are true:

1. `aop add --resume <feature-id>` is detected by a live supervisor without waiting for the next full wave cycle.
2. Detection occurs within the configured poll interval.
3. The active CLI logs that the request was detected and whether it was queued or deferred.
4. Queue and cluster mutation still happen only through `RunCoordinator`.
5. The design introduces a separate enrollment class instead of adding more control-plane logic into `SupervisorRuntime`.
6. Admitted features enter the wave implied by their persisted status rather than always re-entering planning.
7. If a newly admitted feature targets an earlier phase than the currently executing wave, the coordinator dispatches it via a checkpoint mini-pass at the next safe boundary instead of waiting for a full loop restart.
8. Reactive wake signaling is optional and improves latency, but durable polling remains sufficient for correctness.
9. Explicit retry under an active run re-enrolls through the same enrollment pipeline instead of spawning a second supervisor.
10. The default scheduler is replaceable with a future organizer-agent scheduler.
11. Deferred requests remain durable and visible; they are not silently marked applied.
12. Restarting the supervisor does not lose pending enrollment work.
13. Existing run lease, session ownership, and reconciler invariants continue to hold.

---

## 14. Test Plan

### 14.1 Unit Tests

Add tests for:

- poll interval detection of pending requests
- wake-hint-triggered early detection without requiring the next interval
- duplicate pending request fingerprints
- scheduler decision mapping
- deferred requests remaining pending
- ready decisions draining exactly once
- stop/start lifecycle behavior

### 14.2 Coordinator Tests

Add or update tests for:

- applying ready decisions at safe checkpoints
- immediate rebalance when capacity exists
- planning feature admitted during build causing a planning mini-pass at the next safe checkpoint
- QA feature admitted during planning or build causing the correct status-routed dispatch
- deferred requests remaining pending
- reject reasons for already active/queued/terminal features
- no duplicate queue insertion

### 14.3 Supervisor Integration Tests

Add integration tests for:

- submitting an add request during a live run and observing detection without restart
- request remaining pending while current worker unit is in-flight
- request applying at next safe checkpoint
- request detected through wake hint with polling fallback still available
- resumed `building` feature entering build rather than planning
- resumed `qa` feature entering QA rather than planning
- explicit retry under an active run re-enrolling via the execution enrollment path
- restart and recovery of deferred work

### 14.4 Status/UX Tests

Add tests for:

- status output showing detected pending requests
- status output showing deferred reasons
- runtime logging for detection, queue, and defer events

---

## 15. Open Questions

1. Should `pending_deferred` become a first-class durable request status, or should it remain `pending` with richer outcome metadata?
2. Should the initial scheduler always allow queue growth, or should queue admission be configurable to reserve queue ordering for the future organizer agent?
3. What is the correct operator-facing SLA for “near-real-time” detection in deterministic mode versus interactive mode?
4. Should the initial wake signal be implemented as an in-memory notifier only, or should it also support an artifact-backed trigger for multi-process robustness?

Recommended answer for this milestone:

- keep durable status as `pending`
- include defer reason in status projection
- allow queue growth by default
- set the default poll interval to 2000 ms
- treat wake signaling as a best-effort optimization layered on top of polling

---

## 16. Summary

This spec replaces coarse, loop-bound request handling with a dedicated enrollment service, optional reactive wake signaling, checkpoint mini-pass dispatch, and a pluggable scheduler architecture.

It solves the immediate problem:

- `aop add` becomes reactive enough to feel live without sacrificing deterministic coordinator ownership

while preserving the future direction:

- an external organizer agent can later become the scheduling policy without forcing a second redesign of polling, request persistence, or coordinator ownership.
