> 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/phase01-session01-event-ingest-contract-reconciliation/spec.md).

# Session Specification

**Session ID**: `phase01-session01-event-ingest-contract-reconciliation` **Phase**: 01 - Core Runtime Hardening **Status**: Completed **Created**: 2026-05-29 **Package**: Cross-cutting (`packages/protocol`, `apps/server`, `apps/hooks`) **Package Stack**: TypeScript protocol and server, JavaScript ESM hooks, Markdown docs

***

## 1. Session Overview

This session reconciles FactionOS event ingest with the current hook scripts and the historical OpenClaw-style `/event` payloads documented in `EXAMPLES/`. The current server dispatches by `eventName` or `hook`, while the hook scripts also send hook-specific `type` values and later hook events identify the hero by the Claude session id. This creates a contract gap: `SessionStart` spawns an internal hero id, but later hook payloads use the saved `sessionId` as `heroId`.

The session makes the ingest boundary explicit and tested. Protocol types define the accepted hook and compatibility payload vocabulary, the server normalizes incoming payloads at the route boundary, selected OpenClaw `type`-only events become supported compatibility behavior, unknown named events remain bounded opaque mission events, and docs distinguish shipped behavior from planned historical parity.

***

## 2. Objectives

1. Define a typed ingest contract for Claude hook payloads and selected OpenClaw compatibility payloads.
2. Resolve hero identity consistently from `heroId`, `sessionId`, or hook aliases without requiring hooks to wait for server responses.
3. Add first-class server handling and tests for selected hook-specific payload types while preserving opaque fallback behavior for unsupported events.
4. Update API, hook, and protocol documentation so source, tests, and docs agree.

***

## 3. Prerequisites

### Required Sessions

* [x] Phase 00 - Source of Truth and Cleanup Plan: provides PRD authority, conventions, cleanup rules, and direct `EXAMPLES/` source policy.

### Required Tools/Knowledge

* Node.js 20 or newer.
* npm workspace commands from the root package.
* Vitest test project conventions in `vitest.config.ts`.
* Current `/event` implementation in `apps/server/src/routes/event.ts`.
* Current hook scripts in `apps/hooks/src/`.
* Shared event and hero contracts in `packages/protocol/src/`.

### Environment Requirements

* Work from the repository root.
* Keep `EXAMPLES/` as reference-only input; do not copy old runtime code.
* Do not add runtime dependencies unless a task explicitly justifies them.

***

## 4. Scope

### In Scope (MVP)

* Developer can post current Claude hook payloads to `/event` and have later session-scoped payloads resolve to the spawned hero - add session id aliasing and focused tests.
* Integrator can post selected OpenClaw `type`-only payloads (`hero_active`, `mission_start`, `file_access`, `bash_command`, `hero_idle`) and receive accepted hero or mission outcomes - normalize payloads at the server boundary.
* Server can emit first-class events for existing protocol surfaces (`file_access`, `bash_command`, `awaiting_input`, `input_received`, `permission_request`) where current hook payloads already carry enough data.
* Server can keep `subagent_spawn`, `subagent_complete`, `git_dirty`, and other unsupported or not-yet-typed payloads as bounded opaque `mission_event` frames - document explicit disposition.
* Maintainer can verify hook and compatibility payloads with protocol, server, and hook fixture tests.
* Reader can rely on `docs/api/event-api-hook-contracts.md`, `docs/api/README_api.md`, `apps/hooks/README_hooks.md`, and `packages/protocol/README_protocol.md` for the shipped ingest vocabulary.

### Out of Scope (Deferred)

* UI redesign or new event rendering - Reason: Phase 02 owns product surface completion.
* War Room relay or remote federation ingest - Reason: Phase 05 owns Worker integration.
* Full orchestration controls such as spawn, resume, fork, handoff, task queues, and verification - Reason: Phase 03 owns orchestration.
* Route-specific authorization, export redaction, archive retention, and LLM transfer confirmation - Reason: later Phase 01 sessions own those hardening areas.
* Direct promotion or copying of files from `EXAMPLES/` - Reason: historical artifacts remain quarantined source evidence.

***

## 5. Technical Approach

### Architecture

Protocol changes lead the work. Add a small ingest contract module under `packages/protocol/src/` that names supported hook event names, selected OpenClaw compatibility event types, accepted request payload shapes, and the accepted response envelope. Export it from the protocol index so server tests and docs can refer to one vocabulary.

Server behavior should move parsing and normalization out of the Express route into a focused `apps/server/src/lib/eventIngest.ts` helper. The route stays small: validate the body shape, normalize the dispatch key, resolve a hero from `heroId` or `sessionId`, perform the state transition, emit protocol events, and return `{ accepted: true, heroId?, missionId? }`. Unknown named events continue to emit bounded opaque `mission_event` frames instead of crashing.

Hero identity is resolved by storing the external session id on the spawned hero and supporting lookup by session id. This matches current hook behavior, which saves the Claude session id locally and cannot wait for the server-generated hero id before later hook scripts run.

### Design Patterns

* Boundary normalizer: keep untrusted request parsing in one server helper.
* Discriminated unions: model ingest event names and selected type-only compatibility payloads in protocol code.
* Explicit fallback: route unsupported named payloads to bounded `mission_event` frames and document what remains opaque.
* Cross-package contract first: update protocol, then server behavior, then docs.

### Technology Stack

* TypeScript 5.9 in `packages/protocol` and `apps/server`.
* JavaScript ESM in `apps/hooks`.
* Express 4 route handling.
* Vitest 4 node project tests.
* Existing npm workspace scripts.

***

## 6. Deliverables

### Files to Create

| File                                                | Purpose                                             | Est. Lines |
| --------------------------------------------------- | --------------------------------------------------- | ---------- |
| `packages/protocol/src/ingest.ts`                   | Shared hook and compatibility ingest contract types | \~170      |
| `packages/protocol/tests/ingest.test.ts`            | Protocol-level ingest vocabulary tests              | \~120      |
| `apps/server/src/lib/eventIngest.ts`                | Server request normalization and dispatch helpers   | \~220      |
| `apps/server/tests/eventIngest.test.ts`             | Focused `/event` compatibility and fallback tests   | \~240      |
| `apps/hooks/tests/hookPayloads.test.js`             | Hook fixture tests for emitted payload shape        | \~180      |
| `apps/server/tests/fixtures/event-ingest/README.md` | Notes for current and historical payload fixtures   | \~40       |

### Files to Modify

| File                                     | Changes                                                        | Est. Lines |
| ---------------------------------------- | -------------------------------------------------------------- | ---------- |
| `packages/protocol/src/index.ts`         | Export ingest contract module                                  | \~2        |
| `packages/protocol/src/heroes.ts`        | Add optional `sessionId` to hero spawn/runtime contracts       | \~10       |
| `apps/server/src/managers/heroRoster.ts` | Store and resolve heroes by external session id                | \~35       |
| `apps/server/src/routes/event.ts`        | Use normalizer and emit selected first-class events            | \~120      |
| `apps/server/tests/routes.test.ts`       | Keep existing lifecycle tests aligned with alias behavior      | \~80       |
| `vitest.config.ts`                       | Include hook fixture tests in the node project                 | \~5        |
| `docs/api/event-api-hook-contracts.md`   | Document shipped ingest vocabulary and compatibility decisions | \~120      |
| `docs/api/README_api.md`                 | Update concise `/event` mapping                                | \~50       |
| `apps/hooks/README_hooks.md`             | Align hook handler claims with first-class and opaque behavior | \~70       |
| `packages/protocol/README_protocol.md`   | Document ingest contract ownership                             | \~25       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] `SessionStart` stores a session alias and later hook payloads using that alias start missions, record tool use, and complete missions.
* [ ] Selected OpenClaw `type`-only payloads are either supported with state changes or explicitly rejected from first-class handling with tests and docs.
* [ ] Unknown named events stay accepted and emit bounded opaque `mission_event` frames.
* [ ] Hook-specific `file_access`, `bash_command`, `awaiting_input`, `input_received`, and `permission_request` payloads produce documented protocol events when enough fields are present.

### Testing Requirements

* [ ] Protocol ingest vocabulary tests written and passing.
* [ ] Server route tests cover Claude hook payloads, type-only compatibility, missing dispatch keys, unknown named events, and session alias resolution.
* [ ] Hook fixture tests cover payload shape for the active handler set.
* [ ] Manual review confirms docs and tests describe the same shipped contract.

### Non-Functional Requirements

* [ ] Hook handlers remain dependency-light, silent, fire-and-forget, and tolerant when the server is unavailable.
* [ ] `/event` remains tolerant of malformed or partial payloads without crashing.
* [ ] No optional service, API key, hosted account, or remote relay is required.
* [ ] Historical artifacts remain reference-only and are not imported into runtime paths.

### Quality Gates

* [ ] All spec artifacts ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Focused tests pass before validation.

***

## 8. Implementation Notes

### Key Considerations

* The current hook flow saves the Claude `sessionId` locally and later sends it as `heroId`; the server must resolve this alias instead of requiring hook scripts to block for a generated hero id.
* OpenClaw payloads are compatibility inputs, not an excuse to support every historical route or event immediately.
* `EXAMPLES/` files should be cited in docs for traceability but never copied as source implementation.

### Potential Challenges

* Session alias drift: Store aliases in `HeroRoster` and test both `heroId` and `sessionId` resolution paths.
* Too much event parity: Limit first-class handling to existing protocol event types and keep untyped historical events opaque.
* Hook fixture flakiness: Prefer testing pure emitted payload shape or bounded local HTTP collection with deterministic timeouts.
* Documentation drift: Update concise docs and detailed contract docs in the same implementation session.

### Relevant Considerations

* \[P00] **Historical artifacts quarantined**: Use `EXAMPLES/` as source evidence only, and keep runtime implementation in current source.
* \[P00] **Prompt and path privacy**: Payloads can include prompts, commands, cwd, and file paths; tests should avoid real private paths and docs should call out local-only handling.
* \[P00-apps/server+packages/protocol] **Typed surface exceeds implementation**: Support only the selected ingest vocabulary and document opaque fallback.
* \[P00] **Local-first boundary**: Keep compatibility behavior independent of API keys, hosted services, adapters, and Cloudflare.
* \[P00-packages/protocol] **Protocol leads cross-package work**: Add shared types before changing server dispatch.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* External `/event` payloads are malformed, partial, type-only, or use old field names.
* Session aliases fail to resolve and silently drop real hook activity.
* Unsupported historical events appear to be supported because they are accepted opaquely.
* Prompt, command, cwd, and file path fields leak into tests or docs beyond the local contract.

***

## 9. Testing Strategy

### Unit Tests

* Protocol tests for ingest event name and compatibility type unions.
* Server helper tests for normalization, hero/session id resolution inputs, and unsupported dispatch results.
* Hook fixture tests for handler payload shape and truncation behavior.

### Integration Tests

* `/event` route tests for Claude hook lifecycle from `SessionStart` through `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, and `Stop`.
* `/event` route tests for OpenClaw `type`-only `hero_active`, `mission_start`, `file_access`, `bash_command`, and `hero_idle`.
* WebSocket emission tests where existing helpers allow deterministic capture.

### Manual Testing

* Run a local server with mock mode disabled.
* Post representative payloads from the docs and confirm accepted responses, roster state, mission state, and emitted event logs.
* Review docs tables against passing tests.

### Edge Cases

* Missing `eventName`, `hook`, and `type`.
* Unknown named event with no active mission.
* `sessionId` present but no spawned hero.
* `heroId` and `sessionId` both present but disagree.
* Tool payload without an active mission.
* Oversized prompt, command, file path, or detail fields.

***

## 10. Dependencies

### External Libraries

* None expected. Use existing Express, nanoid, and Vitest dependencies.

### Internal Dependencies

* `packages/protocol/src/events.ts`
* `packages/protocol/src/heroes.ts`
* `apps/server/src/routes/event.ts`
* `apps/server/src/managers/heroRoster.ts`
* `apps/server/src/managers/missionManager.ts`
* `apps/hooks/src/*`

### Other Sessions

* **Depends on**: Phase 00 source-of-truth cleanup.
* **Depended by**: Session 02 Hook Runtime Safety, Session 04 Server Routes and Authorization Boundaries, Session 05 WebSocket Hydration and Archive Export Privacy, Session 07 Runtime Contract Documentation.

***

## 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/phase01-session01-event-ingest-contract-reconciliation/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.
