Metadata-Version: 2.5
Name: ironsilk
Version: 0.9.37
Summary: Tide runtime for domain/workspace context management (published under the ironsilk codename)
License: MIT
Keywords: context,domain,hermes,ironsilk,miadi,navigator,runtime,tide,tmux,workspace
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Requires-Dist: aiosqlite>=0.20
Requires-Dist: click>=8.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Provides-Extra: controller
Requires-Dist: libtmux>=0.28; extra == 'controller'
Provides-Extra: daemon
Requires-Dist: watchdog>=4.0; extra == 'daemon'
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: studio
Requires-Dist: textual>=0.50; extra == 'studio'
Provides-Extra: telegram
Requires-Dist: httpx>=0.27; extra == 'telegram'
Requires-Dist: python-telegram-bot>=21.0; extra == 'telegram'
Description-Content-Type: text/markdown

# ironsilk — Domain/Workspace Context Management
<!-- Ref: jgwill/Miadi#265; jgwill/Miadi#401 -->

> **Naming note** — This package is published on PyPI as `ironsilk`
> (https://pypi.org/project/ironsilk/). Its command is `tide`, and its Python
> import path is `tide_runtime`. The naming decision is tracked in jgwill/Miadi#359.
>
> **State-root note** — `~/.miadi/navigator` is the canonical default runtime
> state root. `MIADI_HOME` is the preferred override. Workspace/project config
> lives at `.miadi/tide.yaml`.

### Naming Migration Debt

| Identifier | Classification | Decision Surface |
| --- | --- | --- |
| `runtime/tide-runtime` | Current contract | repository path/package layout |
| `ironsilk` | Current release name | PyPI distribution name |
| `tide` CLI | Current contract | canonical console entry point |
| `tide_runtime` | Migration debt | Python import/module path |
| `MIADI_HOME` | Current contract | preferred state-root env var |
| `~/.miadi/navigator` | Current contract | default Navigator state root |
| `.miadi/tide.yaml` | Current contract | workspace/project config filename |
| `tide-runtime.service` | Migration debt | user-service unit name |


## description
`ironsilk` currently ships the Tide Runtime implementation behind
the `tide` CLI. It gives William and local agents instant
orientation across active development domains and many terminal surfaces.

## What It Does

- **R1 — Domain Detection:** Auto-detects which domain each terminal/tmux pane belongs to, using a priority chain of signals (env var → tmux name → git remote → path prefix → heuristic)
- **R4 — Terminal Focus:** Lists or switches tmux focus to a domain's terminal group
- **R2 — Context Engine:** Always-on background collector that builds a queryable snapshot of all terminal activity, scoped by domain
- **R5 — Approval Queue:** Proposed terminal actions flow through a review queue before execution
- **R7 — Session Store:** Named persistent sessions resumable from desktop or Telegram (`/resume <name>`)
- **R8 — Skill Interface:** Packaged as a Tide skill, callable from agent workflows
- **Operator cockpit:** lists, peeks and steers tmux and herdr panes. Every send passes a steer gate (live target, controller posture, interactive terminal)
- **Agent continuity:** names the agent in each tmux pane and brings the agents back after a tmux restore (`tide agents list`, `tide agents restore`, 0.9.35+)

**Issue:** [jgwill/Miadi#265](https://github.com/jgwill/Miadi/issues/265)

The TypeScript side of the same runtime (`@miadi/tide`, `@miadi/tide-contract` and
Miadi's `/tide` cockpit) is described in
[How tide helps the work](https://github.com/jgwill/Miadi/blob/main/runtime/tide-runtime/docs/how-tide-helps-the-work.md).

---

## Quick Start

```bash
# Install
cd runtime/tide-runtime
pip install -e .

# Configure domains
mkdir -p ~/.miadi/navigator
cp examples/domains.yml ~/.miadi/navigator/domains.yml
# Edit ~/.miadi/navigator/domains.yml to match your domain roots

# Detect domain for current directory
tide detect

# Detect for a specific path
tide detect --cwd ~/src/Miadi

# List terminals for a domain
tide focus miadi

# Show context snapshot
tide context

# Start background daemon
tide daemon

# Install/start as a user service
tide service install --interval 15 --now

# Release/install smoke gate
tide doctor --release-target 0.9.36

# Which agent runs, or ran, in each tmux pane
tide agents list

# Operator cockpit: know/enter existing tmux work
tide operator terminals
tide operator peek 7 --lines 80
tide operator attach 7
tide operator registry save
tide operator registry last-known
tide operator registry drift
tide operator checkpoint
tide operator checkpoint --write
tide operator steer-proposal 7 --message "continue from the visible prompt"
tide session new ava-260512 --cwd /usr/local/src/ironsilk
tide session attach ava-260512
```

## Fast Demo Path For This Branch

Want to try the workspace/context slice without touching your real
`~/.miadi/navigator` state?

```bash
cd runtime/tide-runtime
pip install -e .
./examples/demo-miadi-workspace.sh /usr/local/src/mightyeagle
```

What this does:
- sets `MIADI_HOME` to an isolated temp directory
- writes a one-domain config pointed at the repo you pass in
- captures a persisted context snapshot when the demo scene is frozen
- runs `detect`, `ecf observe`, `scene activate`, `scene list`, `scene snapshot`, and `scene resume`
- leaves the generated SQLite/files behind so you can inspect them after the run

You can also point the runtime at any alternate state directory yourself:

```bash
export MIADI_HOME=/tmp/tide-demo
tide detect --cwd /usr/local/src/mightyeagle
```

Preferred override for new setups:

```bash
export MIADI_HOME=/tmp/tide-demo
tide detect --cwd /usr/local/src/mightyeagle
```

---

## Configuration

### `~/.miadi/navigator/domains.yml` — Domain Registry

```yaml
domains:
  - name: miadi
    aliases: [main, mia]
    roots:
      - ~/src/Miadi
      - ~/work/Miadi
    remotes:
      - "github.com/jgwill/Miadi"
    env_var: "MIADI_DOMAIN"
    tmux_pattern: "miadi-*"

  - name: aureon
    aliases: [aur]
    roots:
      - ~/src/aureon
    remotes:
      - "github.com/jgwill/aureon"
    tmux_pattern: "aureon-*"
```

See `examples/domains.yml` for a full example.

### `~/.miadi/navigator/config.yml` — Navigator Config

```yaml
mode: observer           # observer | controller
daemon_interval: 5.0     # seconds between context polls
session_db: ~/.miadi/navigator/sessions.db
context_log: ~/.miadi/navigator/context/log.ndjson
domains_config: ~/.miadi/navigator/domains.yml
```

See `examples/config.yml` for full options.

---

## Commands

The examples below use the canonical `tide` CLI.

### Detection

```bash
# Detect domain for current directory
tide detect

# Detect for specific cwd
tide detect --cwd ~/src/Miadi

# Detect for specific tmux pane
tide detect --pane %42

# Detect all panes in current tmux session
tide detect --all-panes
```

### Focus (R4)

```bash
# List terminals for a domain (observer mode)
tide focus miadi

# List matching desktop terminal windows (Terminator/Konsole/etc.)
tide focus miadi --desktop
tide focus miadi --desktop --format json

# Activate a matching desktop window (controller mode + approval required)
tide mode controller
tide focus miadi --desktop --activate
tide focus miadi --desktop --activate --window-id 0x00eaf0d8

# Activate tmux focus to domain pane group (controller mode required)
tide mode controller
tide focus miadi
```

### Operator Cockpit

These commands are the first "avoid context rot" surface. They are deliberately
small: list the live tmux targets, inspect recent scrollback without attaching,
and print the exact attach/switch commands before changing focus.

```bash
# List existing tmux sessions/panes and their attach commands
tide operator terminals
tide operator terminals --format json

# Inspect what is happening in a session or pane without attaching
tide operator peek 7 --lines 80
tide operator peek %7 --format json

# Print the commands for entering a target
tide operator attach 7

# Execute attach/switch from an interactive controller terminal
tide mode controller
tide operator attach 7 --run

# Persist terminal awareness as append-only JSONL
tide operator registry save
tide operator registry last-known
tide operator registry drift

# One read-only "know before entering" checkpoint
tide operator checkpoint
tide operator checkpoint --target 7 --peek-lines 20
tide operator checkpoint --format json
tide operator checkpoint --write
tide operator checkpoint --target 7 --peek-lines 20 --write

# Human-reviewable follow-up proposal; no send is performed
tide operator steer-proposal 7 --message "continue from the visible prompt"
tide operator steer-proposal 7 --message-file prompt.md --write
tide operator steer-proposal 7 --message "continue" --peek-lines 40
tide operator steer-proposal 7 --message "continue" --format json
```

The registry is a read-only awareness surface after capture: `save` appends a
timestamped snapshot under the Navigator state directory, `last-known` reads the
newest persisted snapshot, and `drift` compares current tmux state with that
snapshot. It stores observed tmux fields separately from inferred Navigator
fields such as domain and attach commands.

`operator checkpoint` combines current terminals, the last-known registry
metadata, drift summary, stale/last-seen hints, and safe entry commands. It does
not capture scrollback unless `--target` is provided.

Add `--write` to save a portable Markdown and JSON handoff under
`MIADI_HOME/operator/checkpoints/` (or the resolved Navigator state directory).
This serializes the same checkpoint report;
it does not attach, resume, or mutate terminals.

`operator steer-proposal` creates a reviewed-message artifact for a specific
target. It prints manual `tmux send-keys` suggestions only; Navigator does not
send input, attach, resume, or require controller mode.

`operator send` prints the guarded send for one target. With `--run` it types
the message, and only when the steer gate passes: the target is a live pane,
the mode is controller with an unexpired lease, and stdin is a terminal (or a
reviewed service set `TIDE_ALLOW_NON_INTERACTIVE_RUN=1`). `@miadi/tide` applies
the same three checks before its own sends.

### Agents (tmux restore)

```bash
# Which agent runs, or ran, in each pane of the running tmux server
tide agents list
tide agents list --json

# After tmux restored its panes: relaunch the agents tide last saw there
tide agents restore --dry-run --force   # print the plan, touch nothing
tide agents restore                     # what the tmux post-restore hook runs
```

The daemon records the agent in each pane every snapshot: its pid, session id,
command line and launch alias, read from the pane's process tree,
`~/.claude/sessions/<pid>.json` and the binding lines under
`/src/_sessiondata/data/terminal_bindings.jsonl`. `agents restore` reads the
last snapshot from before the running tmux server started. Agents that were
running are relaunched with their launch alias and `--resume <id>`, 10 seconds
apart, most recently active first, while 16 GiB of memory stays available.
Agents that had exited get their command typed without Enter. Claude and hermes
resume with `--resume <id>`, pi with `--session <id>`. It runs once per tmux server start
(jgwill/Miadi#691, jgwill/gaia#89).

### Context (R2)

```bash
# Show full context snapshot
tide context

# Filter by domain
tide context --domain miadi

# JSON output
tide context --format json

# Context from last 30 minutes
tide context --since 30m
```

### Sessions (R7)

```bash
# Tmux-style named session plan (dry-run by default)
tide session new ava-260512 --cwd /usr/local/src/ironsilk
tide session attach ava-260512

# Execute from a local human-controlled terminal
tide mode controller
tide session new ava-260512 --cwd /usr/local/src/ironsilk --run
tide session attach ava-260512 --run

# Create a named session
tide session create aureon-refactor-2025

# Resume a session
tide session resume aureon-refactor-2025

# List all sessions
tide session list

# Archive a session
tide session archive aureon-refactor-2025
```

`session new` and `session attach` are tmux-backed verbs for the v0.7.0
Hermes-Agent CLI base. They print exact tmux commands by default; execution
requires `ACTIVE_CONTROLLER` mode and an interactive local terminal.

### Doctor / Release Gate

```bash
tide doctor
tide doctor --release-target 0.9.36 --strict
tide doctor --release-target 0.9.36 --require-daemon --strict
```

`doctor` checks package version, state/config shape, tmux availability, daemon
ping/context readiness, user service hints, and the operator/session CLI
surfaces needed before workspace registry work.

### Mode

```bash
# Check current mode
tide mode

# Switch to active controller (enables tmux actions)
tide mode controller

# Switch back to observer (safe default)
tide mode observer
```

### Tide Studio

```bash
tide studio --cwd /path/to/workspace
```

Tide Studio is the Textual workspace cockpit. The Explorer opens directories,
opens `.miadi/tide.yaml` project configs, and previews small UTF-8 text files.
File preview is read-only in observer mode. When the operator has explicitly
enabled controller mode, the file panel becomes editable and writes only after
Save or `Ctrl+S`.

### Daemon

```bash
# Start daemon (blocks; use & or a process manager)
tide daemon

# Start with custom poll interval
tide daemon --interval 10

# Scene launch opens a terminal/editor for a stored workspace. On systems with
# Terminator installed, Navigator prefers Terminator for new terminal windows.
tide scene activate /path/to/project --launch

# Daemon writes to:
#   ~/.miadi/navigator/context/latest.json    (last snapshot)
#   ~/.miadi/navigator/context/log.ndjson     (rolling log)
#   ~/.miadi/navigator/daemon.pid             (PID file)
```

### User Service

The ironsilk daemon should run as a **user service**, not a root/system service.
It observes your user terminals, desktop windows, tmux panes, and user-owned
state. The service writes a systemd user unit at
`~/.config/systemd/user/tide-runtime.service`.

```bash
# Install and start immediately
tide service install --interval 15 --now

# If you want an explicit isolated runtime state:
tide service install --interval 15 --state-home ~/.local/state/tide-runtime --now

# Control it later
tide service status
tide service restart
tide service stop
tide service uninstall
```

If `~/.miadi/navigator` exists but is not accessible to your current user,
Navigator falls back to `~/.local/state/tide-runtime`. If `systemctl --user`
is unavailable, keep using `tide daemon` in a terminal or a local process
manager until the desktop session imports user services.

### Cockpits

There is not yet a floating desktop window. The working surfaces are:

- `tide studio` — the Textual cockpit: Explorer, presence rail of herdr agents,
  focus pane with a controller-gated steer card
- Miadi's `/tide` page — the web cockpit, on `@miadi/tide`: panes grouped by
  domain, peek, steer, and annotating an agent's last reply from a phone or a desk
- `tide context`, `tide focus <domain> --desktop`, `tide session ...` — the CLI views
- `app/docs/miadi-agent/navigator` in Miadi — a design mock of the overlay,
  approval queue and Telegram continuity (first commit c83c2a91, 2026-04-29).
  It is not a running surface.

The desktop overlay is specified in
`rispecs/tide-runtime/05-ui-surface.spec.md`, but implementation remains the
next product step.

---

## Architecture Overview

```
domains.yml ──► DomainDetector ──► ContextEngine ──► Daemon
                                              │
                                     ┌────────┼─────────┐
                                     │        │         │
                                 SessionStore  ApprovalQ  Focus
                                     │
                                    CLI (tide)
```

**Data flow (Phase 1):**
1. `DomainDetector` reads `domains.yml` and detects domain identity for tmux panes
2. `ContextEngine` polls tmux and desktop windows every N seconds and builds `ContextSnapshot`
3. `Daemon` runs `ContextEngine.start_continuous()` and writes to `~/.miadi/navigator/`
4. `tide` commands query the daemon or directly invoke detection/focus

---

## Integration with Hermes Skill Ecosystem

The navigator is packaged as a Tide skill at `skills/navigator.skill.yml`. Any Hermes-class agent can load this manifest and call:

- `navigator.focus(domain)` — list or activate domain terminal group
- `navigator.context(domain?, format?)` — get context snapshot
- `navigator.propose(action)` — queue a terminal action for approval
- `navigator.session.resume(name)` — rehydrate a named session
- `navigator.session.list()` — list all sessions

See `rispecs/tide-runtime/04-skill-contract.spec.md` for full action definitions.

---

## Development

```bash
# Install in development mode
pip install -e ".[dev]"

# Run directly
python -m tide_runtime.cli --help

# Use the installed console entry point.
tide --help
```

### Project Structure

```
runtime/tide-runtime/
├── tide_runtime/
│   ├── models.py             # data models
│   ├── config.py, paths.py   # config and the MIADI_HOME state root
│   ├── domain_detector.py    # R1 — domain detection
│   ├── context_engine.py     # R2 — context (tmux, desktop windows, agents); snapshot index kept 7 days
│   ├── sqlite_async.py       # async SQLite helpers
│   ├── focus.py, desktop_focus.py, desktop_observer.py  # R4 — terminal and window focus
│   ├── approval_queue.py     # R5 — action approval
│   ├── session_store.py, tmux_session.py  # R7 — named sessions
│   ├── scene.py              # workspaces (`scene` is the deprecated alias)
│   ├── terminal_inventory.py, terminal_registry.py, terminal_checkpoint.py  # operator awareness
│   ├── terminal_steer.py, terminal_send.py  # steer proposals and the gated send
│   ├── herdr.py              # read/steer client for the herdr multiplexer
│   ├── zellij_bridge.py      # Zellij plugin ingest
│   ├── pane_agents.py        # which agent runs, or ran, in each pane
│   ├── launchers.py          # launch aliases and per-kind resume rules
│   ├── agent_restore.py      # `tide agents restore`
│   ├── audit.py, release_gate.py, service.py, daemon.py
│   ├── tui/                  # `tide studio`
│   └── cli.py                # tide CLI
├── docs/
│   └── how-tide-helps-the-work.md  # the Python runtime and its TypeScript side
├── foundations/              # inquiry artifacts behind the Studio slices
├── skills/
│   └── navigator.skill.yml   # Tide skill manifest
├── examples/
├── tests/
├── pyproject.toml
├── RELEASE.md                # publishing (from gaia: upload as jgi)
└── README.md
```

---

## Specs

- Master: `rispecs/tide-runtime/00-tide-runtime-master.spec.md`
- Domain Detection: `rispecs/tide-runtime/01-domain-detection.spec.md`
- Context Engine: `rispecs/tide-runtime/02-context-engine.spec.md`
- Session Store: `rispecs/tide-runtime/03-session-store.spec.md`
- Skill Contract: `rispecs/tide-runtime/04-skill-contract.spec.md`
- UI Surface: `rispecs/tide-runtime/05-ui-surface.spec.md`
- Daemon Lifecycle: `rispecs/tide-runtime/06-daemon-lifecycle.spec.md`
- Mode And Safety: `rispecs/tide-runtime/07-mode-and-safety.spec.md`
- Threat Model: `rispecs/tide-runtime/08-threat-model.spec.md`
- Telegram Bridge: `rispecs/tide-runtime/09-telegram-bridge.spec.md`
- Domain Relational Graph: `rispecs/tide-runtime/10-domain-relational-graph.spec.md`
- Zellij Augmentation: `rispecs/tide-runtime/11-zellij-augmentation.spec.md`
- Tmux Focus Tracking: `rispecs/tide-runtime/12-tmux-focus-tracking.spec.md`
- TmuxAI Observe/Act Harness: `rispecs/tide-runtime/13-tmuxai-observe-act-harness.spec.md`
- Presence-First Studio: `rispecs/tide-runtime/14-presence-first-studio.spec.md`
- Agent Continuity: `rispecs/tide-runtime/15-agent-continuity.spec.md`
- Steering Clients And Cockpit: `rispecs/tide-runtime/16-steering-clients-and-cockpit.spec.md`
- Status: `rispecs/tide-runtime/STATUS.md`

Academic grounding for the multiplexing and workspace model lives in Miadi's
`foundations/terminal-workspace-orchestration/`, `foundations/tide-runtime-tmuxai/`
and `foundations/ai-native-terminal-multiplexer-integration-layer/`.
