> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase20-session08-managed-agent-lifecycle-control/spec.md).

# Session Specification

**Session ID**: `phase20-session08-managed-agent-lifecycle-control` **Phase**: 20 - Orchestration Actionability Execution **Status**: Not Started **Created**: 2026-06-28 **Package**: null **Package Stack**: mixed TypeScript across `packages/protocol`, `apps/server`, and `apps/web`

***

## 1. Session Overview

This session adds the managed-agent boundary required before Hero/Lineage controls can claim real lifecycle control. Current hook-ingested Claude Code and Codex CLI sessions are observations only, and the existing `HeroLifecycleManager` records lifecycle intent without controlling a process. The session keeps those observed sessions record-only while adding a FactionOS-owned managed session path that can stop, restart, or message only sessions the local server created or explicitly registered.

It is next because Phase 20 has already made queue, campaign, terminal, Git, and file execution truthful and recoverable. The remaining user-facing gap is hero lifecycle control: the product must not show `Stop`, `Restart`, or `Message` as real actions unless a local manager can prove ownership, readiness, cleanup behavior, and bounded execution evidence.

The session is cross-package by design. Protocol owns managed-session capability and lifecycle result fields, the server owns process or PTY control plus execution-run evidence, and the web app owns readiness-aware Hero/Lineage verbs that distinguish managed control from observed record-only intent.

***

## 2. Objectives

1. Define protocol-owned managed-agent session metadata, supported lifecycle actions, and compact lifecycle execution evidence.
2. Add a server-side `ManagedAgentSessionManager` that can control only FactionOS-owned processes or PTY sessions.
3. Route Hero/Lineage lifecycle commands through managed execution for supported stop, restart, and message actions, while keeping observed sessions record-only.
4. Update the web Hero/Lineage workbench so control verbs appear only for managed ready sessions and unsupported provider actions remain unavailable.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase19-session09-heroes-and-lineage` - Provides the existing Hero/Lineage command-center surface, lifecycle command manager, and lineage roster.
* [x] `phase20-session01-truthful-capability-baseline` - Establishes truthful record-only wording for observed hero lifecycle controls.
* [x] `phase20-session02-queue-terminal-execution` - Provides the bounded `TerminalSessionManager` control primitives for FactionOS-owned PTY sessions.

### Required Tools Or Knowledge

* Node 26.2.0 and npm 11.16.0 from `.spec_system/CONVENTIONS.md`.
* Existing `CommandCenterHeroLifecycleCommand`, `CommandCenterExecutionRun`, `HeroLifecycleManager`, `OrchestrationCommandCenterManager`, `TerminalSessionManager`, and Hero/Lineage web helpers.
* Current local-first redaction rules for commands, prompts, terminal output, paths, tokens, provider payloads, broad rows, and WebSocket events.
* `tree-kill` is already declared by `apps/server` and may be used only for manager-owned process ids.

### Environment Requirements

* Local repo checkout with npm workspaces installed.
* Test fixtures may spawn disposable local child processes, but production behavior must stay local and FactionOS-owned.
* No provider credentials, hosted account, Worker proxy, remote execution, Docker runtime, analytics, database, or new native dependency is required.

***

## 4. Scope

### In Scope (MVP)

* Operators can see whether a Hero/Lineage record is observed-only or managed - Add compact managed-session metadata, readiness state, and supported action labels.
* Operators can stop a managed session - Kill a FactionOS-owned process or PTY session with cleanup on scope exit for all acquired resources, timeout escalation, execution-run evidence, and duplicate-trigger prevention while in flight.
* Operators can restart a managed session - Restart the same managed command or PTY session only when restart is configured, preserving prior session history and reporting failed or unavailable restart results.
* Operators can message a managed PTY session - Write scoped input only when the PTY is running and the action is explicitly supported, with schema-validated input and explicit error mapping.
* Observed hook sessions stay record-only - Hook-ingested Claude Code and Codex CLI records continue to show record-intent copy and never claim process control.
* Unsupported provider actions remain unavailable - `change_model`, `change_permission_mode`, and `change_isolation_mode` return unavailable before execution unless a real provider-specific mechanism exists.
* Broad surfaces stay compact - REST lists, WebSocket events, UI rows, docs, and tests expose only safe ids, provider labels, state labels, execution ids, command labels, cwd labels, and compact result summaries.

### Out Of Scope (Deferred)

* Arbitrary control of external Claude Code or Codex CLI sessions not created by FactionOS - Reason: no ownership, process, PTY, or provider authority is available.
* New full agent launcher UX for spawning Claude/Codex from scratch - Reason: this session defines and wires the control boundary; launch workflows can be added later using the same manager.
* Model, permission, or isolation changes - Reason: no provider-specific execution mechanism exists in the current codebase.
* Remote, hosted, Worker, container, or cloud-backed agent lifecycle control - Reason: Phase 20 remains local-first and no-claim for remote or hosted execution.
* Raw prompt, transcript, terminal-output, or command-body detail surfaces - Reason: scoped sensitive content must not appear in broad lifecycle rows or events.
* Database, persistence schema, or migration work - Reason: command-center lifecycle state remains in-memory manager-owned local state.

***

## 5. Technical Approach

### Architecture

Protocol should extend the existing command-center lifecycle contract instead of creating a separate hero-control domain. Add managed-session metadata fields to `CommandCenterHeroLifecycleCommand` and its event entries, including a managed session id, provider label, managed readiness, supported actions, execution run id, and compact result or unavailable labels. Parser helpers should reject blocked raw payload fields and keep message input request-scoped.

Server behavior should center on a new `ManagedAgentSessionManager`. The manager should register only FactionOS-owned process or PTY records with provider label, safe command label, cwd label, readiness state, supported actions, cleanup policy, and optional restart command. For process-backed sessions it can stop by signaling the owned process and escalating through `tree-kill` if needed. For PTY-backed sessions it should delegate stop, restart, and input to `TerminalSessionManager` only when the session id is owned and running. Unsupported, missing, external, stale, duplicate, and failed actions should map to explicit lifecycle and execution-run states.

Hero lifecycle submission should route through managed execution only when the request references a ready managed session with the requested action in its supported action list. Otherwise it should preserve the current observed-only behavior: record safe intent, mark unsupported controls unavailable or approved-not-executing, and never claim execution. Execution runs should use the existing command-center run model with family/kind pairs such as `subagent` and `stop_subagent`, `message_hero`, or `resume_subagent`, and should expose only compact attachments.

Web behavior should derive labels from managed readiness. The Hero/Lineage workbench can show `Stop managed session`, `Restart managed session`, and `Message managed session` only for records with a ready managed session and matching supported action. Observed records keep `Record stop intent`, `Record message intent`, and unavailable action copy. Controls must keep accessible labels, focus states, explicit loading, empty, error, offline, and duplicate-in-flight behavior.

### Design Patterns

* Protocol-first contracts: managed lifecycle fields and parsers land before server and web consumers.
* Manager-owned runtime boundary: process ownership, PTY ownership, cleanup, idempotency, state transitions, and compact evidence stay in server managers.
* Fail closed before execution: unowned, observed-only, unsupported, stale, non-running, or duplicate actions return unavailable or record-only results before process control.
* Broad-summary plus scoped-detail split: broad rows and WebSocket frames expose labels and ids only, never prompts, command bodies, terminal output, transcripts, paths, tokens, or provider payloads.
* Capability-driven UI verbs: visible action text is derived from actual supported actions, not from desired lifecycle intent.

***

## 6. Deliverables

### Files To Create

| File                                                     | Purpose                                                                                              | Est. Lines |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ---------- |
| `apps/server/src/managers/managedAgentSessionManager.ts` | Manager for FactionOS-owned process and PTY lifecycle control.                                       | \~280      |
| `apps/server/tests/managedAgentSessionManager.test.ts`   | Unit coverage for owned process stop, PTY message, restart failure, duplicate triggers, and cleanup. | \~220      |

### Files To Modify

| File                                                             | Changes                                                                                                                                                   | Est. Lines |
| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `packages/protocol/src/orchestrationCommandCenter.ts`            | Add managed lifecycle metadata, supported action fields, execution run id, parser validation, and compact event entries.                                  | \~180      |
| `packages/protocol/src/rest.ts`                                  | Keep lifecycle REST request and response aliases aligned with managed fields.                                                                             | \~40       |
| `packages/protocol/tests/orchestrationCommandCenter.test.ts`     | Cover managed lifecycle parsing, supported actions, execution ids, unavailable states, and blocked raw-field rejection.                                   | \~160      |
| `apps/server/src/lib/commandCenterValidation.ts`                 | Parse managed session ids, expected revisions, idempotency keys, and scoped message input with schema-validated input and explicit error mapping.         | \~120      |
| `apps/server/src/managers/heroLifecycleManager.ts`               | Route supported managed actions to the managed session manager while preserving observed-only record-intent behavior.                                     | \~220      |
| `apps/server/src/managers/orchestrationCommandCenter.ts`         | Inject managed lifecycle dependencies, persist managed command state, and emit lifecycle plus execution updates.                                          | \~140      |
| `apps/server/src/routes/commandCenter.ts`                        | Return managed lifecycle mutation results and emit compact lifecycle/execution events with duplicate-trigger prevention while in flight.                  | \~80       |
| `apps/server/src/routes/event.ts`                                | Keep hook-observed Claude/Codex lifecycle observations record-only and include safe observed labels only.                                                 | \~60       |
| `apps/server/src/server.ts`                                      | Instantiate and inject `ManagedAgentSessionManager` with the existing terminal session manager.                                                           | \~60       |
| `apps/server/tests/heroLifecycleManager.test.ts`                 | Cover managed stop/restart/message execution and observed-only record-intent fallback.                                                                    | \~180      |
| `apps/server/tests/commandCenterValidation.test.ts`              | Cover managed lifecycle route validation and blocked raw input rejection.                                                                                 | \~80       |
| `apps/server/tests/commandCenterRoutes.test.ts`                  | Cover route-level managed stop execution, observed-only intent, unsupported action unavailable state, WebSocket event privacy, and execution run linkage. | \~220      |
| `apps/server/tests/eventIngest.test.ts`                          | Prove hook-ingested observed sessions continue to record intent only.                                                                                     | \~80       |
| `apps/web/src/lib/orchestrationApi.ts`                           | Add managed lifecycle request fields and response validation for action submission.                                                                       | \~90       |
| `apps/web/src/lib/commandCenterUi.ts`                            | Add readiness-aware lifecycle labels, action availability, managed result copy, and safe metadata rendering.                                              | \~140      |
| `apps/web/src/components/orchestration/HeroLineageWorkbench.tsx` | Render managed stop/restart/message controls only when supported, with loading, error, offline, focus, and duplicate-in-flight states.                    | \~180      |
| `apps/web/src/store/useGameStore.ts`                             | Normalize managed lifecycle fields from REST and WebSocket snapshots.                                                                                     | \~70       |
| `apps/web/src/store/useWsClient.ts`                              | Sanitize managed lifecycle event entries without blocked raw fields.                                                                                      | \~60       |
| `apps/web/tests/orchestrationApi.test.ts`                        | Cover managed lifecycle request serialization and response validation.                                                                                    | \~90       |
| `apps/web/tests/commandCenterUi.test.ts`                         | Cover managed versus observed lifecycle labels, unavailable copy, and redaction.                                                                          | \~120      |
| `apps/web/tests/HeroLineageWorkbench.test.tsx`                   | Cover readiness-based controls, duplicate in-flight handling, offline disabling, and accessible action labels.                                            | \~160      |
| `apps/web/tests/CommandCenterPanes.test.tsx`                     | Cover Hero/Lineage integration inside the command-center panes.                                                                                           | \~100      |
| `apps/web/tests/commandCenterStore.test.ts`                      | Cover managed lifecycle WebSocket/store normalization.                                                                                                    | \~80       |
| `tests/e2e/orchestration-command-center.e2e.ts`                  | Add browser proof for a managed stop result in the Hero/Lineage workbench.                                                                                | \~120      |
| `apps/server/README_server.md`                                   | Document managed lifecycle control, process ownership, PTY action limits, and no external-session control claim.                                          | \~50       |
| `apps/web/README_web.md`                                         | Document readiness-aware Hero/Lineage verbs and observed-only fallback.                                                                                   | \~40       |
| `docs/api/README_api.md`                                         | Document managed lifecycle route behavior, compact events, unsupported actions, and privacy boundary.                                                     | \~60       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] A managed fixture process can be stopped, records an executed command-center execution run, and leaves a compact lifecycle result in Hero/Lineage state.
* [ ] Managed restart failure preserves prior session history and returns failed or unavailable state without deleting the earlier lifecycle record.
* [ ] Managed message writes only to a running owned PTY session and rejects missing, stopped, or unowned sessions before execution.
* [ ] `change_model`, `change_permission_mode`, and `change_isolation_mode` return unavailable before execution with product-facing recovery copy.
* [ ] Hook-ingested or observed-only Claude/Codex sessions show record-only intent and never use process-control verbs.
* [ ] Broad REST responses, WebSocket events, UI rows, docs, and tests do not expose raw prompts, command bodies, terminal output, transcripts, broad absolute paths, tokens, provider payloads, or raw process internals.

### Testing Requirements

* [ ] Protocol tests cover managed lifecycle metadata, supported actions, execution run ids, unavailable states, and blocked raw-field rejection.
* [ ] Server tests cover owned process stop, PTY message, restart failure, unsupported actions, observed-only fallback, route events, execution-run linkage, and duplicate-trigger prevention.
* [ ] Web tests cover managed versus observed labels, readiness-based buttons, offline/error states, in-flight guards, safe metadata, and store normalization.
* [ ] Browser e2e proves a managed stop result appears in the Hero/Lineage workbench.

### Non-Functional Requirements

* [ ] No lifecycle action controls a process or PTY that was not created or registered by FactionOS.
* [ ] Managed stop, restart, and message actions are idempotent or duplicate-trigger protected while in flight.
* [ ] Managed process cleanup runs on manager disposal and local server shutdown.
* [ ] Sensitive developer data remains local and scoped; no hosted, Worker, provider, analytics, or remote execution behavior is introduced.
* [ ] Existing terminal, Git, file, queue, campaign, and observed lifecycle behavior remains compatible.

### Quality Gates

* [ ] All files ASCII-encoded
* [ ] Unix LF line endings
* [ ] Code follows project conventions
* [ ] Primary user-facing surfaces contain product-facing copy only
* [ ] Focused protocol, server, web, browser, root quality, and `git diff --check` commands pass

***

## 8. Implementation Notes

### Working Assumptions

* Cross-package scope is intentional: the analyzer reports `package: null`, the selected session stub lists `packages/protocol`, `apps/server`, and `apps/web`, and the feature spans shared contracts, local runtime control, and cockpit UI. Planning can proceed with `Package: null` because all task paths are repo-root-relative and the affected packages are explicit.
* Managed lifecycle control should build on existing terminal primitives: `TerminalSessionManager` already owns PTY input, kill, restart, output scoping, and cleanup semantics for FactionOS-created terminal sessions. Planning can proceed by wrapping those safe primitives instead of inventing a separate PTY layer.
* Direct external Claude/Codex process control is not defensible: current hook sessions are observed telemetry and provide no process authority. Planning can proceed by leaving observed rows record-only while adding a manager-owned path for future and test-backed FactionOS-created sessions.
* Stop is the first executable product proof: the session stub requires a managed fixture process stop result and the codebase already has command-center execution runs. Planning can proceed by making stop, restart, and message narrow and evidence-backed without adding a full launch workflow.

### Conflict Resolutions

* The UI already has lifecycle buttons, but current labels intentionally say record intent. The chosen interpretation is to keep those labels for observed rows and introduce control verbs only when managed readiness and supported actions are present.
* `restart` currently maps to unavailable in `HeroLifecycleManager`, while the session requires restart for supported managed sessions. The chosen interpretation is conditional restart: unavailable for observed or unconfigured sessions, executable only for managed sessions with a restart command or PTY restart support.
* Existing event ingestion promotes lifecycle observations into command-center records. The chosen interpretation is that ingestion remains observational and cannot attach managed authority unless a manager-owned session record exists.

### Key Considerations

* \[P19] Executor claims are family-scoped: managed-agent control is ready only for the exact stop/restart/message paths with ownership, audit, cleanup, redaction, tests, docs, and browser evidence.
* \[P19] Scoped detail stays separate from broad rows: raw prompts, command bodies, terminal output, transcripts, provider payloads, broad paths, and process internals stay out of broad lifecycle records.
* \[P03-packages/protocol] Protocol leads cross-package work: managed lifecycle metadata and parser validation land before server and web consumers.
* \[P19] Command-center state is manager-owned: idempotency, revisions, execution runs, event emission, and bounded snapshots stay in managers.
* \[P07] Redaction is boundary-specific: route responses, WebSocket events, UI rows, docs, tests, and screenshots each need explicit minimization.

### Potential Challenges

* Process ownership can be overclaimed: require manager registration before any control action and test unowned ids as unavailable.
* Restart can erase history: keep the prior managed session record and append a new failed or unavailable lifecycle result instead of replacing earlier evidence.
* Message input can leak sensitive text: keep raw message input request-scoped and store only a bounded safe summary.
* Web labels can drift: derive button text from managed readiness and supported actions, not from action enum names alone.
* Event privacy can regress: route and WebSocket tests must assert no raw command, output, transcript, path, token, or provider payload appears in broad frames.

### Relevant Considerations

* \[P19] **Executor claims are family-scoped**: Managed lifecycle controls need exact executable proof before showing control verbs.
* \[P19] **Scoped detail stays separate from broad rows**: Lifecycle events expose compact labels and ids only.
* \[P03-packages/protocol] **Protocol leads cross-package work**: Shared lifecycle fields lead the server and web changes.
* \[P19] **Command-center state is manager-owned**: The lifecycle manager and command-center manager own execution state and compact updates.
* \[P19-apps/server] **`node-pty` is optional**: PTY-backed message/restart behavior must fail closed when PTY support is unavailable.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* State-mutating lifecycle actions running twice or targeting stale state when users click repeatedly or WebSocket frames replay.
* FactionOS controlling an external observed process that it did not create or register.
* Raw prompts, message input, command bodies, terminal output, transcripts, broad paths, tokens, provider payloads, or process internals leaking into broad rows, events, docs, browser screenshots, or tests.

***

## 9. Testing Strategy

### Unit Tests

* Protocol tests for managed lifecycle metadata, supported actions, execution run ids, unavailable states, and blocked raw-field rejection.
* Server manager tests for owned process stop, cleanup on dispose, PTY message, restart failure, unsupported actions, duplicate triggers, and unowned-session rejection.
* Web helper tests for managed versus observed labels, action availability, safe metadata, unavailable copy, and redaction.

### Integration Tests

* Command-center route test that registers a managed fixture process, submits stop, verifies the process is stopped, and confirms lifecycle plus execution events are compact.
* Route test that submits the same action for an observed-only session and confirms it records intent without execution.
* Event ingest test that proves hook observations continue to produce record-only lifecycle state.
* Web pane test that renders managed control verbs only for supported ready records and observed record-intent copy for all other records.

### Runtime Verification

* Playwright app test seeds a managed lifecycle record, triggers `Stop managed session` from Hero/Lineage, observes a product-facing executed result, and confirms no raw command text, terminal output, transcript, broad path, token, or provider payload appears in the visible row.

### Edge Cases

* Managed session id is missing, unknown, stale, or unowned.
* Managed session is already stopped when stop is requested.
* Stop timeout requires escalation.
* Restart is requested without a restart command or with failed spawn.
* Message is requested for a non-PTY session or stopped PTY.
* `change_model`, `change_permission_mode`, or `change_isolation_mode` is requested for any session.
* Local server is offline or the web request times out.
* Duplicate idempotency key is replayed while an action is in flight.
* WebSocket replay updates the same lifecycle record after a local optimistic state.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase19-session09-heroes-and-lineage`, `phase20-session01-truthful-capability-baseline`, `phase20-session02-queue-terminal-execution`
* Depended by: `phase20-session10-templates-and-channel-intake`, `phase20-session11-release-evidence-and-event-privacy`

***

## Next Steps

Run the `implement` workflow step to begin implementation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase20-session08-managed-agent-lifecycle-control/spec.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
