--- type: feature-request id: fr-2026-03-08--threephoenix--state-hub--offline-inbox-ingest target_org: threephoenix target_repo: state-hub status: draft created: "2026-03-08" source_repo: railiance-infra related_workstream_id: bf40b47e-be5b-4930-a7d2-362e76b943bb --- # FR: Offline Inbox Ingest for Degraded-Mode Sessions ## Problem When a Claude session runs on a remote host (e.g. HostEurope) without an active SSH reverse tunnel, the State Hub MCP server is unreachable. Any progress events, decision records, or task status updates that would normally be written via `add_progress_event()` / `record_decision()` are silently lost unless the operator manually replays them from their local machine after the session. This creates a gap in the audit trail and requires manual follow-up that is easy to forget. ## Proposed Solution ### 1. Inbox convention in domain repos Domain repos write pending events to a `state-hub-inbox/` directory as YAML files: ``` state-hub-inbox/ YYYY-MM-DD-.yaml ``` Each file is a structured event: ```yaml type: progress_event # or: decision, task_status_update topic_id: workstream_id: event_type: milestone # matches add_progress_event() event_type values summary: "..." detail: {} status: pending # state-hub sets to "ingested" after processing recorded_at: "YYYY-MM-DD" source_repo: ``` Files are committed to git so they are never lost. ### 2. Ingest command in state-hub Add a `make ingest-inbox` target (or equivalent CLI command) that: 1. Scans registered domain repos for `state-hub-inbox/*.yaml` files with `status: pending` 2. Calls the appropriate API endpoint for each (`add_progress_event`, `record_decision`, etc.) 3. Updates `status: ingested` and commits back (or opens a PR) so files are not replayed Alternatively, the MCP server could expose a `ingest_inbox_file(path)` tool that Claude calls at session start when the hub is reachable, to drain any queued events from previous degraded sessions. ### 3. Session start behaviour At orientation (Step 1), after `get_domain_summary()` succeeds, Claude should: - Glob `state-hub-inbox/*.yaml` in the current repo - For each file with `status: pending`, call the appropriate write tool and mark it ingested This keeps the drain logic in Claude rather than requiring a separate make target. ## Acceptance Criteria - `state-hub-inbox/` files with `status: pending` are reliably ingested on next connected session with no manual intervention - Ingested files are marked so they are not replayed - Works for at minimum: `progress_event`, `decision`, `task_status_update` ## Example See: `state-hub-inbox/2026-03-08-railiance01-bootstrap.yaml` in this repo — the first real offline event that motivated this request. ## Priority Medium. The workaround (manual replay) works but degrades auditability for sessions run from remote hosts, which is the intended production workflow for this project.