Commit Graph

6 Commits

Author SHA1 Message Date
leetcrypt 12ae553ca1 feat(operator): VM marketplace — Phase A registry + Phase B trading
Phase A: host-global VM registry (~/.hh/registry.json) joining opaque
snapshots to their .hh-agent manifests. New src/registry.rs (serde_json),
one Entry per saved VM with cached purpose/status/todo scraped from the
live container at save time. Reconcile-on-read self-evicts pruned images.
/sbx browse TUI lister + operator-side `registry list|show` reader.

Phase B: trading/skill VMs. Entry gains shareable/tags/share_path +
publish/get/list_shareable helpers. New TUI verbs /sbx publish <label>
[tag...], /sbx catalog @user, /sbx pull @user <label>. Wire protocol adds
_sbx:catreq/catalog/pullreq frames (parse_sbx). Receiver auto-loads a
received hh-snap-*.tar, reads the in-image manifest, and self-registers
(kept shareable for re-trade). Reuses the existing E2E /send + ft.rs
streaming transport.

podman gotcha fixed: `podman load` prints registry-qualified
`localhost/hh-snap:<label>` vs docker's bare tag — parse_loaded_tag now
finds the hh-snap: marker anywhere in the line (unit-tested both shapes).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-27 15:21:53 -07:00
leetcrypt 19d5b80a2c feat(operator): hh-agent manifest — VMs carry a self-describing handoff record
Add ICM-aligned agent-manifest tooling so a hack-house sandbox/VM can be
shared, traded, and resumed without a human briefing. manifest.py is a
dependency-light (stdlib + optional PyYAML) library + CLI that writes a
`.hh-agent/` bundle: manifest.yaml (canonical machine record) plus rendered
AGENT.md / last-state.md / summary.md / goals.yaml views.

Wire a `manifest` op into the operator bridge (push/pull/update) that moves the
bundle in and out of the *target sandbox* via the same exec path as write/get,
so the VM itself carries its purpose, goals, user intent, live state, and a
provenance chain — the unit of agent-to-agent work transmission. Pairs with
`spawn`: stamp → push → hand a child "load the .hh-agent manifest and continue."

Proven end-to-end against a real Kali podman container (push → on-disk verify →
update → pull-back) and covered by 6 new offline tests (34 green total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 20:28:48 -07:00
leetcrypt 338e843e85 feat(operator): Phase 6 — relay-mode read (screen) + stop-condition engine (watch)
Completes the remote-drive triad for a broker-owned sandbox the operator can't
exec into directly: keys (in) → watch (wait) → screen (out).

- _sbx:data PTY-relay frames are absorbed into a capped rolling terminal buffer
  (not surfaced as chat); `screen` returns it ansi-stripped (or raw). sandbox.
  strip_ansi handles CSI/OSC/CR noise so output greps cleanly.
- `watch` is a formal stop-condition engine: blocks until a regex matches in the
  screen buffer or chat events, or an idle-quiescence window, or a hard timeout,
  then reports which fired — the autonomy loop's principled wait.
- Skill doctrine updated with the type→wait→read relay loop.

28 offline tests green.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 20:13:08 -07:00
leetcrypt 60215bbdd4 feat(operator): Phase 5 — bootstrap + budgeted recursive spawn
Lets an operator stand up a nested Claude Code operator against another room —
a tree of operators — behind hard guardrails:

- Budget(depth, fanout, cost): depth/fanout are hard caps decremented on every
  descend(); a leaf (depth 0) or a spent level (fanout 0) refuses to spawn,
  stopping a runaway tree. Cost is carried down as a soft ceiling.
- detect_system / install_plan: decide install from what's present; prefer the
  documented npm package `@anthropic-ai/claude-code` or a $HH_CLAUDE_INSTALL
  override — never a guessed URL.
- Credentials are gated OFF by default: a child authenticates itself unless the
  operator explicitly passes allow_creds, and only its own creds, only to a path
  it was handed.
- compose_directive bakes the objective, stop conditions and inherited budget
  into the child's `claude -p` prompt so it self-limits.

`spawn` op + CLI verb default to a dry-run plan (inspect the tree before growing
it); `--go` launches detached on the host. `up`/`serve` take --depth/--fanout/
--cost. 24 offline tests green; dry-run plan verified live through the socket.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 13:38:42 -07:00
leetcrypt 9c1e2921e9 feat(operator): Phase 2 — sandbox drive (exec/write/get) + keystroke relay
Co-located mode: the operator launches its own podman/docker container and
execs into it out-of-band (argv-identical to the native harness), exposed as
`sbx launch|status|down`, `exec`, `write`, `get`. When granted, it can also
drive the room's broker-owned container directly on the same host.

Relay mode primitive: `keys` injects raw bytes into the shared PTY via the
same `_sbx:input` frame a human driver emits — full keyboard control incl. the
stop-vocabulary (ctrl-c/ctrl-d/ctrl-z/ctrl-\, esc, arrows, pager q). A compact
per-session cheat-sheet (`sandbox.KEYS_HELP`, `keys --help-keys`) documents
what each inject does and how to end a stuck program, token-efficiently.

Gating: exec/write/get refuse a host (`local`) inherited from the room; the
room sandbox is only driven when `granted`. Keystrokes are inert until granted.

17 offline tests green; e2e verified against real podman (launch→exec→write→
get round-trip→teardown) and through the CLI socket.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:34:24 -07:00
leetcrypt 7e81a059b9 feat(operator): Phase 1 — Claude-driven room bridge (join/read/say)
Invert the agent model: a headless OperatorBridge(Client) owns the
websocket while a Claude Code session drives it via a unix control
socket. Reuses Client SRP/Fernet and AgentBridge's reconnect/serve
shape. Ships an hh-bridge CLI (up/read/say/roster/status/down) with a
seq'd in-RAM inbox + asyncio.Condition long-poll (read --wait) for
in-turn autonomy. ACL/sandbox-status frames are recorded for later
phases. Sandbox drive, delegation and nesting are out of scope here.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-26 12:19:47 -07:00