> 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/phase10-session03-server-ingest-codex-lifecycle/spec.md).

# Session Specification

**Session ID**: `phase10-session03-server-ingest-codex-lifecycle` **Phase**: 10 - Codex Product Integration **Status**: Complete **Created**: 2026-05-31 **Package**: apps/server, packages/protocol **Package Stack**: TypeScript protocol contracts, Node 20 Express ingest route, in-memory hero and mission managers, Vitest, Biome checks

***

## 1. Session Overview

This session makes Codex lifecycle events first-class data in the local server. Phase 09 added provider-neutral hook names and Codex-safe hook payload normalization, and Phase 10 Sessions 01-02 wired CLI provider selection plus Codex hook installation. The remaining backend gap is that the server ingest path still treats Codex-specific lifecycle details as partial aliases or generic fallback data.

The work updates `packages/protocol` and `apps/server` together. Protocol remains the shared source of truth for bounded Codex ingest fields and `codex-cli` vocabulary, while the server normalizes Codex payload aliases into the existing hero, mission, tool-use, permission, and subagent lineage paths. No new event store, hosted telemetry path, provider transfer, or web surface is introduced.

The expected result is a fixture-driven Codex lifecycle that materializes a `codex-cli` hero and mission from `SessionStart -> UserPromptSubmit -> PreToolUse Bash -> PreToolUse apply_patch -> PermissionRequest -> SubagentStart -> SubagentStop -> Stop`. Existing Claude lifecycle behavior must continue to pass unchanged, and unknown Codex named events must remain bounded opaque `mission_event` frames instead of leaking raw payload bodies.

***

## 2. Objectives

1. Normalize Codex ingest aliases so `tool_name`, `turn_id`, hook event metadata, and agent metadata are handled consistently with existing server fields.
2. Persist Codex sessions as first-class `codex-cli` heroes and missions through the existing roster and mission managers.
3. Route Codex tool use, permission requests, subagent spawn/stop events, and unknown named events without raw prompt, patch, transcript, command-output, token, or MCP argument leakage.
4. Add focused protocol and server tests proving Codex lifecycle behavior while preserving current Claude lifecycle tests.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase10-session02-codex-hook-install-uninstall-and-diagnostics` - provides user-level Codex hook installation and managed hook command output with `FACTIONOS_CLI=codex-cli`.
* [x] `phase10-session01-cli-provider-selection-and-installer-split` - provides provider-aware CLI command routing and local settings behavior.
* [x] `phase09-session03-codex-hook-map-and-codex-specific-handlers` - provides Codex hook map assets and handler coverage for Codex-shaped payloads.
* [x] `phase09-session02-hook-runtime-normalization` - provides shared hook-side normalization and redaction patterns.
* [x] `phase09-session01-contracts-and-naming-baseline` - provides `codex-cli` as protocol-owned provider vocabulary.
* [x] `phase01-session04-server-routes-and-authorization-boundaries` - provides hardened local Express route boundaries and validation conventions.

### Required Tools/Knowledge

* Node 20+ and npm workspace dependencies.
* Current `apps/server/src/lib/eventIngest.ts` normalization and `apps/server/src/routes/event.ts` routing behavior.
* Current protocol ingest contracts in `packages/protocol/src/ingest.ts` and hero CLI values in `packages/protocol/src/heroes.ts`.
* Current Codex hook fixture shape from `apps/hooks/tests/hookRuntime.test.js` and `apps/hooks/hooks.codex.json`.
* Existing Vitest harness pattern in `apps/server/tests/eventIngest.test.ts`.

### Environment Requirements

* No OpenAI, Codex, Anthropic, Claude, hosted, Cloudflare, database, or provider credentials are required.
* Tests must use local in-memory Express harnesses and must not read real `~/.codex`, `~/.factionos`, hook logs, spool entries, or local session archives.
* Test fixtures must be sanitized and must not contain real prompts, tokens, raw patch bodies, command output, transcript paths, local home paths, or MCP argument bodies.

***

## 4. Scope

### In Scope (MVP)

* Server ingest accepts Codex as a first-class CLI - normalize `cli: "codex-cli"` into the protocol `HeroCli` value instead of falling back to Claude.
* Server ingest normalizes Codex tool aliases - support `toolName` and `tool_name` across tool use, permission request, post-tool, apply\_patch, Bash, and MCP-shaped payloads.
* Server ingest normalizes bounded Codex metadata - support `turnId` and `turn_id` only as compact metadata where needed, without promoting raw transcripts or payload bodies.
* Server ingest routes Codex subagents - recognize `SubagentStart` with `type: "subagent_spawn"` and keep `SubagentStop` completion on the typed lineage path.
* Server ingest preserves named dispatch behavior - keep `eventName ?? hook` dispatch as the primary path while adding Codex alias coverage.
* Server ingest keeps unknown Codex named events bounded - emit opaque `mission_event` frames with allowlisted, truncated data only.
* Protocol captures bounded Codex ingest aliases - document and type compact Codex-safe snake\_case fields without expanding sensitive payload ownership.
* Tests prove full Codex lifecycle persistence - drive a sanitized fixture through `/event` and assert hero, mission, tool use, permission, lineage, and completion state.
* Tests prove regression safety - existing Claude lifecycle behavior stays stable and unknown type-only payloads remain unsupported.

### Out of Scope (Deferred)

* Web labels, hero cards, mission filters, replay, and export UI treatment - *Reason: Phase 10 Session 04 owns web Codex awareness.*
* Hook installation, uninstall, trust review, and CLI diagnostics - *Reason: Phase 10 Session 02 already owns those paths.*
* Hosted ingestion, external telemetry, production-hosted validation, or analytics - *Reason: Phase 10 keeps Codex support local-first and no-claim for hosted surfaces.*
* Raw patch body, command output, transcript path, prompt, MCP argument, or token persistence - *Reason: Codex-sensitive data stays blocked by existing redaction boundaries.*
* New provider model taxonomy or OpenAI model tier behavior - *Reason: web display taxonomy is deferred to Session 04 or later.*
* Real executors, remote actions, or approval enforcement - *Reason: guarded execution remains unavailable by design until a separate threat model ships.*

***

## 5. Technical Approach

### Architecture

Keep the server ingest architecture unchanged: `/event` receives hook payloads, `normalizeEventIngest()` classifies dispatch, and `eventRouter()` materializes heroes, missions, tool uses, permission frames, subagent lineage, or opaque mission events. The implementation should normalize Codex field aliases at the boundary so downstream route code can keep using existing helpers and managers.

Protocol changes should be narrow. Add or document bounded snake\_case aliases for Codex-safe ingest metadata in `packages/protocol/src/ingest.ts`, then cover them in `packages/protocol/tests/ingest.test.ts`. Do not introduce sensitive fields as shared contract ownership. Existing `HeroCli` already includes `codex-cli`, so server normalization should import or conform to that vocabulary instead of maintaining a divergent fallback list.

The server should prefer canonical fields when both canonical and alias fields exist. `tool` remains the existing tool-use field, with `toolName` and `tool_name` feeding that path. `turnId` and `turn_id` remain compact metadata and must not create a new lookup key, transcript link, or durable storage path. Unknown Codex named events should use the same bounded opaque mission event mechanism already used for unknown named hooks.

### Design Patterns

* Protocol-first bounded contracts: shared Codex aliases are typed before server-specific consumption.
* Boundary normalization: translate provider aliases once at ingest, then reuse existing roster, mission, permission, and lineage paths.
* Compatibility-preserving dispatch: keep `eventName ?? hook` before any type-only fallback.
* Bounded opaque fallback: preserve observability for unknown named events without raw payload persistence.
* Negative ownership: explicitly avoid raw prompt, patch, command output, transcript, token, path, MCP argument, hosted, and telemetry data ownership.
* Regression-first testing: add Codex coverage beside existing Claude lifecycle tests instead of rewriting them.

### Technology Stack

* TypeScript ES modules in `packages/protocol` and `apps/server`.
* Express 4 route harness with in-memory managers.
* Vitest for protocol and server tests.
* Biome for formatting and linting.

***

## 6. Deliverables

### Files to Create

| File                                                        | Purpose                                                            | Est. Lines |
| ----------------------------------------------------------- | ------------------------------------------------------------------ | ---------- |
| `apps/server/tests/fixtures/event-ingest/codexLifecycle.ts` | Sanitized reusable Codex lifecycle fixture for server ingest tests | \~120      |

### Files to Modify

| File                                                | Changes                                                                                                          | Est. Lines |
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------- |
| `packages/protocol/src/ingest.ts`                   | Add bounded Codex snake\_case alias fields and clarify compact metadata ownership                                | \~40       |
| `packages/protocol/tests/ingest.test.ts`            | Cover Codex alias fields, hook event metadata, tool names, turn ids, and `codex-cli` typing                      | \~80       |
| `apps/server/src/lib/eventIngest.ts`                | Normalize Codex aliases, bounded metadata, opaque allowlist fields, and `SubagentStart` classification           | \~120      |
| `apps/server/src/routes/event.ts`                   | Accept `codex-cli`, consume normalized tool aliases, and preserve existing hero/mission/permission/lineage paths | \~90       |
| `apps/server/tests/eventIngest.test.ts`             | Add full Codex lifecycle, unknown-event, alias, and Claude regression tests                                      | \~180      |
| `apps/server/tests/fixtures/event-ingest/README.md` | Document the sanitized Codex lifecycle fixture and privacy boundaries                                            | \~40       |
| `docs/api/event-api-hook-contracts.md`              | Update source-backed ingest contract notes for Codex lifecycle support and no-hosted-telemetry claims            | \~70       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] A fixture-driven Codex lifecycle materializes a `codex-cli` hero.
* [ ] `UserPromptSubmit` starts a mission for the Codex hero and `Stop` completes it.
* [ ] `PreToolUse` with `tool_name: "Bash"` and `tool_name: "apply_patch"` creates bounded tool-use records through existing mission paths.
* [ ] `PermissionRequest` emits a first-class permission request with the normalized tool name.
* [ ] `SubagentStart` with `type: "subagent_spawn"` and `SubagentStop` update typed subagent lineage and child mission state.
* [ ] Unknown Codex named events emit bounded opaque `mission_event` frames.
* [ ] Unknown type-only payloads remain unsupported unless they use existing allowed compatibility types.
* [ ] Existing Claude lifecycle tests pass unchanged.

### Testing Requirements

* [ ] Protocol tests cover Codex alias contract fields and `codex-cli` payload typing.
* [ ] Server route tests cover the full Codex lifecycle fixture.
* [ ] Server route tests cover unknown Codex named event fallback and bounded opaque metadata.
* [ ] Server route tests cover `toolName` and `tool_name` normalization.
* [ ] Focused protocol and server Vitest suites pass.

### Non-Functional Requirements

* [ ] No raw prompts, patch bodies, command output, transcript paths, MCP argument bodies, token-like values, broad local paths, hosted payloads, or telemetry payloads are persisted.
* [ ] Ingest behavior remains local-first and requires no external provider credentials.
* [ ] Server behavior reuses existing hero, mission, permission, and lineage managers without a second Codex-specific event store.
* [ ] Local server authorization, CORS, rate-limit, body-size, and validation boundaries remain unchanged.
* [ ] Opaque event data is allowlisted and truncated.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] `git diff --check` passes.

***

## 8. Implementation Notes

### Key Considerations

* The session stub lists `apps/server` and `packages/protocol`, so task paths must stay repo-root package-relative.
* `packages/protocol/src/heroes.ts` already owns `codex-cli`; server code should not duplicate provider vocabulary loosely.
* The current server normalizer already reads `session_id` but does not fully normalize `tool_name`, `turn_id`, or Codex agent metadata.
* Keep `eventName ?? hook` dispatch primary. Type-only fallback is for existing compatibility types only.
* `SubagentStart` is currently not a named dispatch branch; add only the `type: "subagent_spawn"` route needed by the session.
* `PermissionRequest` should remain observational. This session does not add Codex approval enforcement or bypass Codex permission review.
* If both canonical and alias fields exist, prefer canonical fields and use aliases only as fallback.

### Potential Challenges

* Raw Codex payloads can contain sensitive fields: mitigate with fixture sanitization, bounded allowlists, and tests that assert raw content is absent.
* Adding snake\_case aliases can drift from hook-side normalization: mitigate by keeping aliases compact and covered in protocol tests.
* Subagent lifecycle can create duplicate child missions: mitigate by reusing existing `missionIdForSubagent()` and duplicate guards.
* Unknown event fallback can over-observe: mitigate by preserving current named opaque behavior with truncation and by keeping unknown type-only payloads unsupported.
* `codex-cli` fallback could accidentally break unknown CLI behavior: mitigate with explicit accepted-value tests and existing fallback regression coverage.

### Relevant Considerations

* \[P03-packages/protocol] **Protocol leads cross-package work**: Codex ingest aliases and CLI vocabulary must be protocol-owned before server behavior relies on them.
* \[P07] **Redaction is boundary-specific**: server ingest and opaque mission events must bound and minimize Codex payload data at the route boundary.
* \[P03-apps/server] **Local server boundary must stay conservative**: route hardening, validation, and local-only defaults remain release-critical.
* \[P09-apps/hooks] **Do not forward raw Codex payloads**: patch bodies, terminal output, transcript paths, token-like values, and MCP arguments stay summarized or redacted.
* \[P09-packages/protocol+apps/hooks] **Provider-neutral hook names need alias discipline**: keep provider-neutral names and Codex aliases aligned without reintroducing Claude-only assumptions.
* \[Security] **P06-S07-HOSTED-VALIDATION**: this session adds local server ingest support only and does not create production-hosted validation claims.

### Behavioral Quality Focus

Checklist active: Yes

Top behavioral risks for this session:

* Codex payload aliases could bypass validation or leak raw fields into mission events.
* `codex-cli` payloads could silently fall back to Claude and produce misleading cockpit data.
* Subagent lifecycle events could duplicate child missions or fail to complete existing lineage.
* Unknown named Codex events could persist oversized or sensitive opaque data.
* Existing Claude lifecycle behavior could regress while adding Codex-specific branches.

***

## 9. Testing Strategy

### Unit Tests

* Protocol ingest tests for bounded Codex alias fields, `AgentHookIngestPayload`, and `codex-cli` typing.
* Server normalization tests through the existing `/event` harness for `toolName`, `tool_name`, `turnId`, and `turn_id`.

### Integration Tests

* Full Express route fixture replay for `SessionStart`, `UserPromptSubmit`, Bash, apply\_patch, `PermissionRequest`, `SubagentStart`, `SubagentStop`, and `Stop`.
* Mission graph assertions for Codex subagent child mission creation and completion.
* Broadcaster event assertions for `internal_hero_spawn`, `mission_start`, `tool_use`, `permission_request`, `subagent_lineage_update`, `mission_complete`, and bounded `mission_event`.

### Manual Testing

* Review focused test output to confirm the Codex lifecycle response includes `heroId` and `missionId` where expected.
* Inspect generated fixture data to confirm it is synthetic and contains no raw prompt, patch, command output, token, transcript path, or local home path.

### Edge Cases

* `toolName` and `tool_name` both present, with canonical field winning.
* `turnId` and `turn_id` both present, with canonical field winning and truncation applied.
* `SubagentStart` received without an active parent mission, producing a bounded degraded lineage event.
* Unknown named Codex event with oversized detail, token-like text, patch-like text, and alias fields.
* Unknown type-only payload stays unsupported and does not emit events.
* Unknown CLI value still falls back to existing safe default.

***

## 10. Dependencies

### External Libraries

* No new external libraries.

### Other Sessions

* **Depends on**: `phase10-session02-codex-hook-install-uninstall-and-diagnostics`, `phase09-session03-codex-hook-map-and-codex-specific-handlers`, `phase09-session02-hook-runtime-normalization`, `phase09-session01-contracts-and-naming-baseline`
* **Depended by**: `phase10-session04-web-codex-awareness`, Phase 11 Codex hardening and validation sessions

***

## Next Steps

Run the implement workflow step to begin AI-led 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/phase10-session03-server-ingest-codex-lifecycle/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.
