# Feature Spec: Headless Standby Runtime and Dashboard Bootstrap (AOP)

> **Purpose of this document**: Define how AOP runs persist in headless standby, how `run`/`resume`/`retry` can launch with the dashboard, and how the dashboard auto-starts a headless orchestrator when none is active.

**Version:** 1.0
**Date:** 2026-03-16
**Status:** Draft
**Roadmap Mapping:** M52
**Depends On:**

- `spec-files/completed/agentic_orchestrator_single_global_orchestrator_spec.md`
- `spec-files/completed/agentic_orchestrator_add_feature_to_active_execution_spec.md`
- `spec-files/completed/agentic_orchestrator_reactive_execution_enrollment_spec.md`
- `spec-files/completed/agentic_orchestrator_persistent_worker_runtime_spec.md`

---

## 0. Scope

This spec covers the following user requests:

1. The CLI should not exit once current features finish; it should remain in a standby mode waiting for new feature submissions.
2. The dashboard should automatically ensure a headless standby orchestrator exists when the dashboard starts.
3. `aop run`, `aop resume`, and `aop retry` should support `--headless` and `--dashboard`.
4. `aop run --headless --dashboard` should launch the dashboard automatically.

Out of scope:

- Quick Launch page design details
- organizer/spec-ordering logic
- token telemetry and per-phase model policy

### 0.1 Required Standards

All implementation derived from this spec MUST preserve:

- single active run-lease ownership per repository
- deterministic enrollment and wake-up semantics for newly submitted work
- existing runtime artifact compatibility under `.aop/**`
- normalized structured responses and error codes
- explicit separation between foreground batch mode and headless standby mode

### 0.2 OOP and Architecture Guardrails (Mandatory)

Implementation MUST follow:

- **KISS**: extend the existing runtime lifecycle with a standby state instead of introducing a second runtime stack.
- **SRP**: standby lifecycle, dashboard bootstrapping, browser-open behavior, and CLI flag parsing MUST remain separate concerns.
- **SOLID-oriented design**:
  - open/closed for future runtime states or boot strategies without rewriting the coordinator loop
  - interface segregation between runtime state reporting, dashboard launch management, and CLI orchestration
  - dependency inversion so CLI/dashboard startup depends on a shared runtime-launch seam rather than embedding process logic everywhere
- **Hexagonal alignment**: keep long-lived runtime behavior inside supervisor/application layers, not in dashboard route code.
- **Composition over inheritance**: compose standby behavior into `RunCoordinator`/runtime services rather than subclassing supervisors.
- **High cohesion / low coupling**: browser-opening and dashboard process management must not leak into enrollment or lease services.

---

## 1. Problem Statement

The current supervisor lifecycle is batch-oriented:

- `run` and `resume` return after the active queue drains
- the run lease is released immediately at completion
- dashboard startup assumes the runtime already exists

This makes dashboard-driven intake awkward because the operator must first start a separate CLI run or restart execution after the previous queue completes.

The requested behavior is a persistent local control plane:

- headless orchestrator lives in standby
- new dashboard or CLI submissions attach to the existing standby run
- dashboard startup can bootstrap that runtime when needed

---

## 2. Design Summary

### 2.1 Standby Runtime

Introduce a new run-level runtime mode:

- `active`
- `standby`
- `stopped`

When started in headless mode, the supervisor:

1. acquires the run lease
2. processes active work normally
3. when the queue drains, transitions to `standby` instead of exiting
4. keeps the enrollment service and lease heartbeat alive
5. exits only on explicit stop/fatal unrecoverable error

### 2.2 CLI Flags

Add flags to `run`, `resume`, and `retry`:

- `--headless`
- `--dashboard`

Semantics:

- `--headless` means the CLI invocation is launching or attaching to a long-lived background-oriented runtime rather than a foreground batch lifecycle.
- `--dashboard` means ensure the dashboard is running and open it automatically after the runtime is available.

Normative rule:

- `--dashboard` on these commands implies `--headless` unless explicitly rejected by the CLI contract.

### 2.3 Dashboard Auto-Boot

When the dashboard boots and no active/standby runtime exists, it MUST be able to start one in headless standby mode.

This boot path MUST:

- check for an existing fresh run lease first
- be idempotent under concurrent requests
- avoid starting duplicate supervisors

Recommended implementation surface:

- dashboard-side bootstrap route or server helper that delegates to a shared runtime launcher

---

## 3. Functional Requirements

### FR-1 Standby Loop

Headless runs MUST remain alive after the active queue drains.

Acceptance criteria:

1. Drained work does not release the run lease immediately in headless standby mode.
2. Enrollment polling or wake-hint logic continues while the runtime is idle.
3. New `aop add` or dashboard launch submissions wake the standby runtime without needing a second supervisor.

### FR-2 Explicit Stop Semantics

Standby runtimes MUST still shut down deterministically.

Acceptance criteria:

1. `aop stop` against the active standby run releases the lease and terminates background runtime ownership.
2. Fatal unrecoverable provider/runtime errors still terminate and report structured failure.
3. Shutdown paths do not leave orphan heartbeat timers or stale runtime session artifacts.

### FR-3 New CLI Flags

`run`, `resume`, and `retry` MUST accept:

- `--headless`
- `--dashboard`

Acceptance criteria:

1. CLI parser, help output, command catalog, and AGENTS/CLAUDE docs are updated together.
2. `--dashboard` is supported on `run`, `resume`, and `retry`.
3. `--headless` can be used without `--dashboard`.

### FR-4 Automatic Dashboard Launch

When `--dashboard` is supplied, AOP MUST:

1. ensure the runtime is started or attached
2. ensure the dashboard server is running
3. open the dashboard URL automatically

Acceptance criteria:

1. The returned payload includes the opened URL and mode.
2. Repeated calls while the dashboard is already running do not spawn duplicate dashboard servers.
3. Open-browser behavior is best-effort and non-fatal if the opener command is unavailable.

### FR-5 Dashboard Auto-Ensures Runtime

Dashboard startup MUST ensure a headless standby runtime exists when appropriate.

Acceptance criteria:

1. First dashboard load against a stopped repo can bootstrap standby mode.
2. If a fresh run already exists, dashboard uses it and does not start another.
3. Bootstrap failure is surfaced as a non-blocking dashboard health state rather than a blank page.

---

## 4. Runtime Contract

### 4.1 Run Metadata

Runtime metadata MUST gain an explicit status field:

```json
{
  "run_mode": "headless",
  "runtime_state": "active",
  "standby_since": null
}
```

When the queue drains in headless mode:

```json
{
  "run_mode": "headless",
  "runtime_state": "standby",
  "standby_since": "2026-03-16T12:00:00.000Z"
}
```

### 4.2 Enrollment Interaction

While in standby:

- `ExecutionEnrollmentService` remains active
- `notifyNewRequestHint()` can promote the runtime back to active processing
- queue mutation remains coordinator-owned

### 4.3 Foreground Compatibility

Existing non-headless `run` and `resume` behavior remains valid:

- process queue
- release lease
- exit cleanly

This spec must not turn every CLI run into a daemon by default.

---

## 5. Dashboard Bootstrap Contract

Recommended API surface:

- `POST /api/runtime/ensure`

Responsibilities:

1. detect whether a fresh active or standby run already exists
2. if not, start headless standby mode for the current repo/project
3. return normalized runtime state payload

Possible response:

```json
{
  "ok": true,
  "data": {
    "status": "started",
    "runtime_state": "standby",
    "run_id": "run:abc123",
    "dashboard_url": "http://localhost:3000"
  }
}
```

---

## 6. File-Level Targets

- `apps/control-plane/src/cli/types.ts`
  - add `headless` and `dashboard` options.
- `apps/control-plane/src/cli/cli-argument-parser.ts`
  - parse new flags.
- `apps/control-plane/src/cli/command-catalog.ts`
  - document new flag usage.
- `apps/control-plane/src/cli/help-command-handler.ts`
  - add flag descriptions for `run`, `resume`, and `retry`.
- `apps/control-plane/src/interfaces/cli/bootstrap.ts`
  - wire headless/dashboard orchestration.
- `apps/control-plane/src/cli/run-command-handler.ts`
  - support headless standby launch path.
- `apps/control-plane/src/cli/resume-command-handler.ts`
  - support headless standby launch path.
- `apps/control-plane/src/cli/retry-command-handler.ts`
  - support retry re-enrollment plus optional headless/dashboard boot.
- `apps/control-plane/src/cli/dashboard-command-handler.ts`
  - add reusable “ensure running” and best-effort browser-open behavior.
- `apps/control-plane/src/supervisor/run-coordinator.ts`
  - add standby transition instead of unconditional exit in headless mode.
- `apps/control-plane/src/supervisor/runtime.ts`
  - expose headless/standby metadata and lifecycle control.
- `apps/control-plane/src/application/services/run-lease-service.ts`
  - preserve fresh lease ownership across standby idle periods.
- `packages/web-dashboard/src/app/api/runtime/ensure/route.ts`
  - new dashboard bootstrap route.
- `packages/web-dashboard/src/app/page.tsx`
  - trigger ensure-runtime flow on initial load as appropriate.

---

## 7. Acceptance Criteria

1. A headless run stays alive in standby after all current features complete.
2. New execution requests can be processed without manually starting a new supervisor.
3. `run`, `resume`, and `retry` support `--headless` and `--dashboard`.
4. `aop run --headless --dashboard` automatically opens the dashboard.
5. Dashboard startup auto-starts headless standby mode if no runtime is active.

---

## 8. Risks and Mitigations

- Risk: standby mode hides dead supervisors behind a fresh lease.
  - Mitigation: explicit runtime-state reporting and heartbeat-health checks must distinguish `standby` from `active`.
- Risk: dashboard auto-boot races with manual CLI boot.
  - Mitigation: use the existing run-lease singleton as the concurrency guard.
- Risk: automatic browser-open breaks headless server environments.
  - Mitigation: opener remains best-effort and non-fatal; allow opt-out by environment flag.
