# Workorder: Task-Local Gateway Context

## Objective

Introduce a task-local gateway context based on Node `AsyncLocalStorage` so Telegram, REST, TUI, scheduler, and background runs can share a common current-session context without mutable cross-run leakage.

## Problem Statement

Current Telegram tools and helpers frequently capture `chatId`, `currentMsg`, `sessionKey`, and tool context in closures. This works, but it makes concurrent run isolation fragile and causes repeated plumbing through many helper constructors.

Hermes uses Python `ContextVar` for gateway session context so tools can resolve active platform/chat/thread/user/run state in an async-safe way.

## Existing Code Anchors

Omnius:
- `packages/cli/src/tui/telegram-bridge.ts:13149` resolves `ToolContext`.
- `packages/cli/src/tui/telegram-bridge.ts:13368` creates `TelegramSubAgent`.
- `packages/cli/src/tui/telegram-bridge.ts:16746` builds reply preference tool using current Telegram message.
- `packages/cli/src/tui/telegram-bridge.ts:16807` builds image analysis tool using current scoped media.
- `packages/cli/src/tui/telegram-bridge.ts:17064` builds Telegram file send tool using current chat/admin state.
- `packages/cli/src/api/serve.ts:7079` registers chat run process leases for API-originated runs.

Hermes:
- `/home/robit/Documents/repositories/hermes-agent/gateway/session_context.py:51` defines session `ContextVar`s.
- `/home/robit/Documents/repositories/hermes-agent/gateway/session_context.py:87` synchronizes session id with environment.
- `/home/robit/Documents/repositories/hermes-agent/tools/env_passthrough.py:30` uses `ContextVar` for per-session environment allowlists.

## Target Architecture

Add `packages/orchestrator/src/runContext.ts` or `packages/cli/src/runtime/run-context.ts` depending on ownership.

Suggested type:

```ts
export interface OmniusRunContext {
  runId: string;
  surface: "tui" | "telegram" | "api" | "scheduler" | "background";
  projectRoot?: string;
  ownerKind?: string;
  ownerId?: string;
  telegram?: {
    chatId: string | number;
    chatType: "private" | "group" | "supergroup" | "channel";
    messageId?: number;
    threadId?: number;
    userId?: number;
    username?: string;
    sessionKey: string;
    toolContext: string;
  };
}
```

API:
- `runWithOmniusContext(ctx, fn)`
- `getOmniusRunContext()`
- `requireOmniusRunContext()`
- `getTelegramRunContext()`

## Phased Implementation

### Phase 0: Concurrency Regression Tests

Tasks:
- Add tests that run two simulated Telegram messages concurrently and prove media/reply tools resolve the correct chat state.
- Add a test that no context is visible outside `runWithOmniusContext`.

Completion metrics:
- Current behavior is characterized before migration.
- Tests fail if global mutable context leaks across runs.

### Phase 1: Add Context Store

Tasks:
- Implement `AsyncLocalStorage<OmniusRunContext>`.
- Add small helpers and type guards.
- Keep it dependency-free.

File-by-file notes:
- `packages/orchestrator/src/runContext.ts` if runner and execution packages should share it.
- `packages/cli/src/tui/telegram-bridge.ts` imports helpers when spawning sub-agents.
- `packages/execution/src/tools/*` should not import CLI internals, so put shared helpers outside CLI if execution tools will consume them.

Completion metrics:
- Unit tests prove nested async calls retain the correct context.
- Missing context produces clear errors only in helpers that require it.

### Phase 2: Wrap Run Entrypoints

Tasks:
- Wrap Telegram sub-agent execution with context.
- Wrap Telegram quick-chat execution with context.
- Wrap REST/API run execution with context.
- Wrap background/scheduler execution if the owner id is available.

Completion metrics:
- Each run emits a context diagnostic with run id and surface.
- Existing tool behavior remains unchanged.

### Phase 3: Migrate Telegram Tools Incrementally

Tasks:
- Update tools that currently capture `currentMsg` to prefer task-local context:
  - reply preference,
  - image/media analysis,
  - file send target defaults,
  - reminder scope,
  - identity memory media resolution.
- Keep explicit constructor arguments as fallback during migration.

Completion metrics:
- Tools work when called through current explicit path.
- Tests prove task-local path works without passing current message through every helper.

### Phase 4: Process Lease Integration

Tasks:
- When registering process leases, default `ownerKind`, `ownerId`, and `projectRoot` from current run context.
- Ensure child environment receives:
  - `OMNIUS_PROCESS_LEASE_ID`,
  - `OMNIUS_OWNER_ID`,
  - `OMNIUS_PROJECT_ROOT`,
  - optional `OMNIUS_RUN_ID`.

Completion metrics:
- Shell/background/API spawned children have correct owner fields without duplicate call-site logic.
- Process lifecycle tests still pass.

### Phase 5: Cleanup and Docs

Tasks:
- Remove redundant parameters only after all call sites are migrated.
- Document the context lifecycle and prohibited usage:
  - never store mutable message objects long-term,
  - never use context outside the current async run,
  - never infer authorization from context alone.

Completion metrics:
- Docs exist under `docs/architecture/`.
- Source tests prevent direct global current-message variables if any are introduced.

## Required Tests

- Async context isolation under concurrent Telegram runs.
- No context outside wrapper.
- Telegram media tool resolves correct chat with context.
- API run context sets lease owner.
- Background task context sets lease owner.

## Rollout Plan

1. Add context store and tests.
2. Wrap run entrypoints.
3. Migrate read-only tools.
4. Migrate mutating tools with explicit authorization checks preserved.
5. Remove redundant plumbing.

## Risks

- Async context can be lost through unawaited promises. Mitigation: tests around timers, streaming callbacks, and tool executors.
- Authorization confusion. Mitigation: context identifies session but does not grant permission.
- Package dependency cycles. Mitigation: place shared context in orchestrator or a small shared package, not CLI.

## Definition of Done

- Current run context is available task-locally across Telegram, API, and background execution.
- Concurrent sessions do not bleed state.
- Tools can use context without importing Telegram bridge internals.
- Process leases can inherit owner metadata from context.
