Skip to content

feat(orchestration): receive session_info harness events into the v2 mirror (B′2)#4710

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
sanil-23:oh-sessinfo-recv
Jul 8, 2026
Merged

feat(orchestration): receive session_info harness events into the v2 mirror (B′2)#4710
senamakel merged 1 commit into
tinyhumansai:mainfrom
sanil-23:oh-sessinfo-recv

Conversation

@sanil-23

@sanil-23 sanil-23 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add the session_info HarnessEventKind to OpenHuman's hand-rolled v2 harness mirror so a wrapped coding-agent's session intro/announce is decoded, classified, and folded into the durable session record — the RECEIVE side of the session_info feature (Track B′).
  • Enrich the sessions table + OrchestrationSession with title / model / handle / repo / branch / capabilities, populated from the intro payload (additive, nullable, migration-backfilled).
  • Treat session_info like status/lifecycle: seq=0, does not advance the wake ordinal, and is hidden from the in-thread bubble/unread surfaces.
  • Wire field names are byte-identical to the TS SessionInfoPayload emitter (snake_case) so the mirror matches the wire.
  • No SDK dependency — extends the existing mirror in place (the Rust-SDK v2 port is deferred).

Problem

TS SDK v2 (SessionEnvelopeV2 + HarnessEventKind) is already merged upstream and the OpenHuman v2 receiver mirror already decodes the content/status/lifecycle kinds. The session_info intro event (spec §2b) — emitted the moment a wrapped session initialises to announce identity, repo/branch, model, and capabilities to its OpenHuman "Master" — had no receiver support: it would fold to Unknown and its metadata would be dropped. OpenHuman couldn't register or render a session's header/metadata from the intro.

The mirror's classify_v2 match is exhaustive (no _ => wildcard), so adding the enum variant requires the classification arm or it won't compile — this is the intended, compile-checked seam.

Solution

  • types.rsSessionInfo(SessionInfoPayload) as the first (adjacently-tagged, snake_case) variant; SessionInfoPayload struct with #[serde(default)] on every field and skip_serializing_if="Option::is_none" on optionals; six enrichment fields on OrchestrationSession.
  • ingest.rsclassify_v2 SessionInfo arm: advances_seq=false, title doubles as the row body, model falls back to the frame's event.model (spec §2b), and the payload folds onto the session record. Threaded through ClassifiedMessagepersist_messageupsert_session.
  • store.rs — additive nullable session columns (fresh DB via SCHEMA_DDL, older store via the per-column add_column_if_missing guard); capabilities stored as a JSON array (empty → NULL so COALESCE preserves a prior list); upsert COALESCEs intro metadata so ordinary events never wipe it and a resumed=true re-intro refreshes rather than duplicates; session_info added to all four no-bubble filters.

Receiver behavior (spec §4): upsert keyed on wrapper_session_id; lazy-create on the first event of any kind (session_info is enrichment, not a prerequisite); idempotent on event.id; resumed=true updates in place.

Tradeoff (accepted): two sources of truth persist (TS SDK v2 + this Rust mirror) until the deferred SDK port; the wire contract is owned by the TS emitter and mirrored here.

Note on scope: this branch stacks the v2 receiver mirror (Track B′1, the pre-existing feat/harness-session-v2-receiver commits) plus the session_info addition (Track B′2). The session_info change itself is the final commit (c6d2850d1); if B′1 lands independently this rebases cleanly onto it.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) — decode + wire-field-name round-trip, thin-payload defaults, modelevent.model fallback, lazy-create + idempotent + resumed-refresh upsert, capabilities JSON codec (null-safe/malformed), and no-bubble hiding from thread/unread.
  • Diff coverage ≥ 80% — every new/changed line is exercised by the added orchestration:: unit tests. Ran cargo test -p openhuman --lib openhuman::orchestration:: locally → 124 passed, 0 failed. (Full-package cargo test compilation is blocked by a pre-existing, unrelated breakage in tests/memory_tree_sync_raw_coverage_e2e.rs — a rebuild_tree arity drift already on main, untouched here.)
  • N/A — Coverage matrix: the tiny.place orchestration DM-receiver domain is not tracked in docs/TEST-COVERAGE-MATRIX.md (no existing row); this extends that untracked domain rather than a matrixed feature.
  • N/A — No matrix feature IDs affected (same reason).
  • No new external network dependencies introduced — pure Rust; serde_json/rusqlite are already dependencies. Tests use tempdir SQLite only.
  • N/A — Does not touch release-cut/manual-smoke surfaces (internal receiver classification + persistence only).
  • N/A — No dedicated tracking issue for the session_info receiver; companion to the existing v2 harness stream (openhuman feat(orchestration): receive typed v2 harness-session stream #4652, tiny.place #229/#230).

Impact

  • Runtime: desktop core only (Rust). No frontend/Tauri change; OrchestrationSession gains additive JSON fields over RPC (extra fields are ignored by older renderers — backward compatible).
  • Migration: additive nullable columns via the existing user_version/table_info guarded migration; idempotent on re-open; existing rows default NULL/empty.
  • Compatibility: decode is fail-soft — an OpenHuman that predates this change folds session_info to Unknown and safely ignores it; a newer receiver reads the enrichment. Wire field names match the TS emitter exactly.
  • Security/privacy: message bodies remain workspace-internal; repo/branch/cwd are only ever received from the paired peer's DM (not broadcast).

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: sanil-23:oh-sessinfo-recv
  • Commit SHA: c6d2850d1 (session_info addition; stacked on the v2 receiver mirror commits)

Validation Run

  • pnpm --filter openhuman-app format:check — N/A (no app/src change)
  • pnpm typecheck — N/A (no TypeScript change)
  • Focused tests: cargo test -p openhuman --lib openhuman::orchestration:: → 124 passed, 0 failed
  • Rust fmt/check (if changed): cargo fmt --check clean on the three changed files; lib compiles (unit-test build green)
  • Tauri fmt/check (if changed): N/A (no app/src-tauri change)

Validation Blocked

  • command: cargo test -p openhuman orchestration:: (full package)
  • error: unrelated pre-existing compile break in tests/memory_tree_sync_raw_coverage_e2e.rs (rebuild_tree takes 3 args, test passes 4) — already on main, not touched by this PR
  • impact: none on this change; validated via the --lib scope above. CI Lite scopes Rust tests to the changed orchestration domain.

Behavior Changes

  • Intended behavior change: OpenHuman now decodes and persists the session_info intro, enriching the session record (title/model/handle/repo/branch/capabilities) instead of dropping it as Unknown.
  • User-visible effect: session header/metadata is available the moment a wrapped session announces itself; the intro never renders as a chat bubble or unread.

Parity Contract

  • Legacy behavior preserved: content/status/lifecycle/unknown classification unchanged; fail-soft Unknown fold intact for genuinely unmodeled kinds.
  • Guard/fallback/dispatch parity checks: no-bubble filter extended consistently across all four store queries; COALESCE upsert mirrors the existing run-state semantics; lazy-create unchanged.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Session details now appear more consistently in stored session summaries, including title, model, handle, repo, branch, and capabilities.
    • Improved support for newer session metadata so sessions can be enriched when that information arrives later.
  • Bug Fixes

    • Session metadata is no longer lost when newer non-metadata events are saved.
    • Hidden session-info updates are excluded from message lists, previews, and unread counts.

@sanil-23 sanil-23 requested a review from a team July 8, 2026 14:20
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds v2 session_info harness event support across orchestration types, ingest classification, and SQLite storage. Session records are enriched with title, model, handle, repo, branch, and capabilities metadata, while session_info rows are excluded from user-visible message threads and unread counts.

Changes

Session Info Enrichment

Layer / File(s) Summary
SessionInfoPayload type and enrichment fields
src/openhuman/orchestration/types.rs
Adds HarnessEventKind::SessionInfo(SessionInfoPayload) variant, SessionInfoPayload struct mirroring the v2 wire schema, and enrichment fields on OrchestrationSession; adds decode/round-trip tests.
Classification into ClassifiedMessage
src/openhuman/orchestration/ingest.rs
Adds enrichment fields to ClassifiedMessage/V2Body, populates them from session_info events in classify_v2 with advances_seq = false, defaults them elsewhere, and wires them through persist_message with new tests.
Schema, migration, and upsert persistence
src/openhuman/orchestration/store.rs
Adds sessions table columns and idempotent migrations, extends upsert_session with COALESCE-based enrichment updates, and adds encode_capabilities/decode_capabilities helpers with tests.
Session read paths and message visibility
src/openhuman/orchestration/store.rs
Updates list_sessions, load_session, map_session_row to expose enrichment fields, and excludes event_kind = 'session_info' from latest_message_preview, list_messages_by_session, and unread_count.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Harness
  participant Ingest as classify_v2/persist_message
  participant Store as upsert_session
  participant DB as sessions table
  participant Reader as list_messages_by_session/unread_count

  Harness->>Ingest: session_info event
  Ingest->>Ingest: extract title, model, handle, repo, branch, capabilities
  Ingest->>Store: enriched OrchestrationSession fields
  Store->>DB: INSERT/UPDATE with COALESCE (preserve prior intro metadata)
  Reader->>DB: query messages/unread count
  DB-->>Reader: exclude event_kind = 'session_info' rows
Loading

Possibly related PRs

  • tinyhumansai/openhuman#4425: Extends the same orchestration/ingest.rs classification and orchestration/store.rs persistence pipeline introduced there with session_info enrichment.
  • tinyhumansai/openhuman#4589: Both PRs modify latest_message_preview and related message visibility logic in the same file.
  • tinyhumansai/openhuman#4652: Extends the same v2 ingest/persistence pipeline with session_info handling in both ingest.rs and store.rs.

Suggested labels: feature, rust-core, agent

Suggested reviewers: oxoxDev

Poem

A whisper arrives, "session_info" they call,
Title, model, and branch — I catch them all! 🐇
COALESCE keeps my burrow's tale intact,
Hidden from threads, but stored as fact.
Hop, hop, upsert — the schema grows anew! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding receive-side session_info support in the v2 orchestration mirror.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6d2850d12

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +448 to +451
let ingest_seq = if classified.advances_seq {
store::next_session_seq(c, agent_id, &classified.session_id)?
} else {
0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prevent state-only events from waking new sessions

For a new v2 session whose first envelope is session_info or status, stamping the row with seq = 0 does not actually keep it out of the wake path: ingest_one still publishes OrchestrationSessionMessage, seed_state loads the persisted row, and has_new_work compares latest 0 against a missing cursor (i64::MIN). That means a purely informational intro/status event can run the orchestration graph and send an unsolicited reply before any real content arrives; skip publishing/waking these events or initialize the cursor so 0 state rows are not considered new work.

Useful? React with 👍 / 👎.

Comment on lines +289 to +294
HarnessEventKind::ApprovalRequest(p) => {
b.body = p.display;
b.tool_name = non_empty(p.tool_name);
b.call_id = p.call_id.and_then(non_empty);
// Drive the roster dot to waiting-approval.
b.status_state = Some("waiting_approval".to_string());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Persist approval request detail for attention items

When a peer sends a v2 approval_request, the new attention path builds the remote approval summary from session.current_detail and its call identity from active_call_id, but this branch only stores status_state plus the message-level call_id. As a result, sessions parked on approval show up in the attention queue without the approval prompt (and without the active call id) even though the payload includes display and call_id; persist display into status_detail and the call id into active_call_id here.

Useful? React with 👍 / 👎.

…mirror

Add the session_info HarnessEventKind to OpenHuman's hand-rolled v2 harness
mirror so a wrapped agent's session intro/announce (spec §2b) is decoded,
classified, and folded into the durable session record.

- types.rs: SessionInfo variant (first, adjacently tagged) + SessionInfoPayload
  struct with wire-byte-identical snake_case field names to the TS emitter
  (spec §2a); enrich OrchestrationSession with title/model/handle/repo/branch/
  capabilities.
- ingest.rs: classify_v2 SessionInfo arm — advances_seq=false (seq=0), title
  doubles as the row body, model falls back to event.model, payload folds onto
  the session record.
- store.rs: additive nullable session columns (capabilities as a JSON array,
  empty→NULL so COALESCE preserves a prior list); upsert COALESCEs the intro
  metadata so ordinary events never wipe it and a resumed=true re-intro refreshes
  rather than duplicates; add session_info to the no-bubble filter so the intro
  never renders as an in-thread chat bubble or counts as unread.

Receiver behavior (spec §4): upsert keyed on wrapper_session_id, lazy-create on
the first event of any kind (session_info is enrichment, not a prerequisite),
idempotent on event.id, resumed=true updates in place.

Tests: session_info decode + wire-field-name round-trip, model/event.model
fallback, lazy-create + idempotent + resumed-refresh upsert, capabilities JSON
codec (null-safe), and no-bubble hiding from thread/unread.
@sanil-23 sanil-23 force-pushed the oh-sessinfo-recv branch from c6d2850 to aedc907 Compare July 8, 2026 14:46
@sanil-23

sanil-23 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review pls

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@sanil-23 On it — kicking off a full review of the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@sanil-23

sanil-23 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jul 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/openhuman/orchestration/store.rs (1)

241-250: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the new enrichment columns in the legacy migration test.

The migration adds six sessions columns, but the existing pre-v2 schema test still asserts only the older status/event columns. Extending that test would catch regressions in the ALTER path for upgraded stores.

Test coverage extension
             for (table, column) in [
                 ("sessions", "status_state"),
                 ("sessions", "current_detail"),
                 ("sessions", "active_call_id"),
+                ("sessions", "title"),
+                ("sessions", "model"),
+                ("sessions", "handle"),
+                ("sessions", "repo"),
+                ("sessions", "branch"),
+                ("sessions", "capabilities"),
                 ("messages", "event_kind"),
                 ("messages", "tool_name"),
                 ("messages", "call_id"),
             ] {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/orchestration/store.rs` around lines 241 - 250, The legacy
migration test needs to cover the new `sessions` enrichment columns added in
`ensure_schema` via `add_column_if_missing`, since it currently only checks the
older status/event columns. Update the pre-v2 schema migration test to assert
that upgraded stores also gain `title`, `model`, `handle`, `repo`, `branch`, and
`capabilities` on `sessions`, so regressions in the ALTER path are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/openhuman/orchestration/store.rs`:
- Around line 241-250: The legacy migration test needs to cover the new
`sessions` enrichment columns added in `ensure_schema` via
`add_column_if_missing`, since it currently only checks the older status/event
columns. Update the pre-v2 schema migration test to assert that upgraded stores
also gain `title`, `model`, `handle`, `repo`, `branch`, and `capabilities` on
`sessions`, so regressions in the ALTER path are caught.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 71b00dbc-2b76-48b9-bb52-fe903e10ff14

📥 Commits

Reviewing files that changed from the base of the PR and between 2e5eb4f and aedc907.

📒 Files selected for processing (3)
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/store.rs
  • src/openhuman/orchestration/types.rs

@senamakel senamakel merged commit c25ab86 into tinyhumansai:main Jul 8, 2026
19 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants