railiance-infra/contrib/feature-requests/fr-2026-03-08--threephoenix--state-hub--offline-inbox-ingest.md
Bernd Worsch ea7270368f chore: add state-hub offline inbox and FR for ingest support
- state-hub-inbox/: convention for queuing progress events during
  degraded-mode sessions (no tunnel to State Hub)
- First pending event: Railiance01 bootstrap milestone (T03-T05)
- contrib/feature-requests/: FR for automated inbox ingest in state-hub
- README documents the drain procedure until automation is in place

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 22:58:51 +00:00

88 lines
2.9 KiB
Markdown

---
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-hosts
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-<slug>.yaml
```
Each file is a structured event:
```yaml
type: progress_event # or: decision, task_status_update
topic_id: <uuid>
workstream_id: <uuid>
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: <repo-slug>
```
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.