# Feature Spec: Single Global Orchestrator Session Topology (AOP)

> **Purpose of this document**: Define the implementation contract for moving from per-feature orchestrator sessions to one global orchestrator session per active run, while preserving deterministic multi-feature delivery and MCP-governed safety.

---

## 1. Objectives

### 1.1 Must-Have Outcomes

- Enforce active-run topology: `1 + 3N`
  - `1` global orchestrator session
  - `N` planner sessions
  - `N` builder sessions
  - `N` QA sessions
- Prevent split-brain orchestration:
  - exactly one active run owner per repo
  - exactly one orchestrator session per active run
- Preserve deterministic orchestration behavior:
  - lock/collision policy
  - plan/patch/gate enforcement
  - auditable state transitions
- Preserve per-feature worktree isolation.

### 1.2 Non-Goals

- No change to worker role definitions.
- No change to MCP tool semantics.
- No replacement of file-backed canonical state.

---

## 2. Topology Model

### 2.1 Current vs Target

Current behavior creates per-feature orchestrator sessions (`4N`).

Target behavior:

- one global orchestrator session per run
- worker sessions per active feature
- queued features do not allocate worker sessions

### 2.2 Active Feature Definition

`N` means active features currently admitted by `max_active_features`.
Queued features are excluded from `N` until promoted to active.

---

## 3. Run Ownership and Singleton Guarantees

### 3.1 Repository Run Lease

A repo must have at most one active orchestrator run at a time.

Canonical lease fields in index:

- `runtime_sessions.run_id`
- `runtime_sessions.owner_instance_id`
- `runtime_sessions.lease_id`
- `runtime_sessions.lease_expires_at`

### 3.2 Start Behavior

On `aop run` start:

1. acquire run lease if absent
2. if active lease exists and is fresh -> fail with `run_already_active`
3. if active lease stale and caller passed takeover flag -> claim lease and continue

Takeover contract:

- CLI flag: `--takeover-stale-run`
- default (flag absent): stale lease does not get reclaimed automatically
- when flag present: reclaim stale lease deterministically and continue
- programmatic invocations SHOULD expose equivalent boolean input: `takeover_stale_run`

### 3.3 Heartbeat

Supervisor MUST refresh run lease heartbeat periodically.
Expired run lease enables deterministic takeover.

---

## 4. Session Ownership and Assignment Rules

### 4.1 Session Graph

- `runtime_sessions.orchestrator_session_id` (single, canonical field in `index.json`)
- `feature_sessions[feature_id] = { planner_session_id, builder_session_id, qa_session_id }` (runtime assignment map)

### 4.2 Assignment for Active vs Queued Features

- Active feature:
  - planner/builder/qa session ids MUST be concrete ids.
- Queued feature:
  - planner/builder/qa session ids MUST be sentinel `"unassigned"`.

Queued features MUST NOT consume session slots or violate `1 + 3N`.

### 4.3 Forbidden Behavior

- creating orchestrator session inside per-feature initialization
- assigning distinct orchestrator ids per feature in same run

---

## 5. Canonical State Contract Deltas

### 5.1 `index.json` Runtime Session Object

Standardize on one object:

- `runtime_sessions.run_id` (string)
- `runtime_sessions.orchestrator_session_id` (string)
- `runtime_sessions.provider` (string)
- `runtime_sessions.model` (string)
- `runtime_sessions.provider_config_ref_hash` (string)
- `runtime_sessions.owner_instance_id` (string)
- `runtime_sessions.lease_id` (string)
- `runtime_sessions.started_at` (date-time)
- `runtime_sessions.last_heartbeat_at` (date-time)
- `runtime_sessions.lease_expires_at` (date-time)

### 5.2 `state.md` Cluster Invariant

Keep existing `cluster` fields for compatibility.

Invariant:

- For each active feature:
  - `state.cluster.orchestrator_session_id == index.runtime_sessions.orchestrator_session_id`

### 5.3 Compatibility Window

- Backfill missing `runtime_sessions` on first run after upgrade.
- Preserve existing per-feature cluster fields until deprecation milestone.

---

## 6. Supervisor Loop Under Global Orchestrator

Each loop iteration:

1. collect per-feature summaries
2. global orchestrator decides prioritization/arbitration
3. dispatch planner/builder/qa work
4. apply role-scoped `ToolClient` calls (`inprocess` or `mcp`)
5. reconcile outcomes and update canonical state

Global orchestrator decisions MUST govern:

- lock contention strategy
- collision resolution ordering
- merge readiness sequencing

---

## 7. Recovery and Failover Algorithm (Normative)

### 7.1 Startup Recovery

1. load index and feature states
2. validate run lease freshness
3. if run lease owned by this instance and fresh -> continue
4. if stale -> reclaim only with takeover policy
5. attempt orchestrator session reattach (bounded timeout)
6. if reattach fails -> create exactly one new orchestrator session
7. increment orchestrator epoch marker in index (for audit)
8. reconcile all active features to current orchestrator session id
9. close/mark orphan worker sessions from prior epoch
10. resume each feature from earliest incomplete phase

### 7.2 Determinism Requirements

- tie-breakers use deterministic ordering by feature id
- reattach timeout defaults are policy-configured
- orphan session cleanup is idempotent

---

## 8. Implementation Plan

### M14: Topology Refactor Foundations

- add global session structure in Supervisor
- create one orchestrator session per run
- remove per-feature orchestrator session creation
- keep per-feature planner/builder/qa creation

### M15: Contract and Schema Updates

- add standardized `runtime_sessions` object to index schema
- update state/index write paths
- implement queued-feature session sentinel handling

### M16: Recovery and Takeover

- implement deterministic reattach-or-recreate algorithm
- implement run lease heartbeat and stale takeover behavior
- implement orphan session cleanup

### M17: Validation and Hardening

- add runtime invariants and enforcement checks
- add integration tests for `N=1`, `N=3`, `N > max_active_features`

### M18: Production Promotion

- align with MCP formalization parity gate
- promote new topology as default production behavior

---

## 9. File-Level Change Targets

- `apps/control-plane/src/supervisor/runtime.ts`
  - global orchestrator lifecycle
  - active/queued session assignment rules
  - recovery and takeover handling
- `apps/control-plane/src/cli/aop.ts`
  - takeover flag contract
  - run ownership/start semantics wiring
- `apps/control-plane/src/core/kernel.ts`
  - index runtime session helpers
  - invariant validation hooks
- `apps/control-plane/src/mcp/tool-client.ts`
  - transport-agnostic call boundary used by supervisor orchestration
- `apps/control-plane/src/mcp/runtime-factory.ts`
  - client/runtime construction used by `aop run`
- `agentic/orchestrator/schemas/index.schema.json`
  - standardized `runtime_sessions`
- `agentic/orchestrator/schemas/state.schema.json`
  - compatibility + invariant notes for cluster fields
- `apps/control-plane/test/*.spec.ts`
  - topology, recovery, takeover, and queue semantics tests

---

## 10. Acceptance Criteria

1. Active run topology is exactly `1 + 3N`.
2. All active features share one orchestrator session id.
3. Queued features use sentinel worker session ids and consume no worker slots.
4. Split-brain prevention works (fresh active run lease blocks second run).
5. Recovery reuses or recreates exactly one orchestrator session deterministically.
6. Existing deterministic tool behavior remains unchanged relative to formalized MCP contracts (auth claims, RBAC intersection, and mutation idempotency).

---

## 11. Risks and Mitigations

- Risk: global orchestrator throughput bottleneck.
  - Mitigation: keep worker phases parallel and orchestrator coordination lightweight.
- Risk: migration breaks existing state snapshots.
  - Mitigation: compatibility backfill and invariant checks.
- Risk: stale lease takeover errors.
  - Mitigation: explicit lease policy, deterministic takeover rules, and audit logs.
- Risk: hidden assumptions in existing tests about per-feature orchestrators.
  - Mitigation: add topology-focused integration tests and remove old assumptions.

---

## 12. Dependency Note

This spec depends on security, idempotency, and transport contracts from:

- `agentic_orchestrator_mcp_formalization_spec.md`

Status note (as of February 28, 2026): foundational MCP formalization artifacts and runtime boundaries are implemented; this topology spec now targets the remaining M14-M18 topology changes on top of that baseline.

Delivery ordering MUST follow the integrated plan in the MCP formalization spec, with topology milestones layered after the formalized tool boundary.
