Files
railiance-infra/contrib/feature-requests/fr-2026-03-08--threephoenix--state-hub--offline-inbox-ingest.md
tegwick 703c57d91c chore(rename): railiance-hosts → railiance-infra
Update all operational references to reflect the new repo name per
ADR-003 (OAS S1 Infrastructure Substrate). Historical text in ADRs
and state-hub-inbox files preserved as-is. Gitea remote URL updated
locally (Gitea repo rename is a manual step).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 00:34:18 +01:00

89 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-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-<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.