Команда Plugin

/dr-orchestrate

Самоуправляемый Datarim pipeline на базе tmux — Phase 2 (Subagent Inference, автономность L2)

Обзор

/dr-orchestrate — референсный non-core плагин фреймворка. Phase 1 (v2.3.0) — lean rule-based tmux runner. Phase 2 (v2.4.0) добавляет subagent inference, который активируется когда rule-based парсер не может классифицировать строку pane, плюс flock-race-safe cooldown и audit schema v2. Автономность плагина теперь L2 (assisted): эскалацию по-прежнему контролирует человек, но unknown prompts больше не упираются в парсер.

Плагин лежит в plugins/dr-orchestrate/ в репозитории фреймворка и включается стандартным CLI (/dr-plugin).

Использование

# Однократно включить плагин
/dr-plugin enable dr-orchestrate

# Опционально: разрешить send-keys (по умолчанию fail-closed)
cp ~/.claude/plugins/dr-orchestrate/user-config.template.yaml \
   ~/.claude/plugins/dr-orchestrate/user-config.yaml
chmod 600 ~/.claude/plugins/dr-orchestrate/user-config.yaml
$EDITOR  ~/.claude/plugins/dr-orchestrate/user-config.yaml   # key_injection: true

# Один цикл Phase 2 (parse → resolver → autonomous-or-escalate)
/dr-orchestrate run

# Сухой прогон для валидации
/dr-orchestrate run --dry-run

# Вручную классифицировать вставленный prompt без consume tmux pane
/dr-orchestrate run --unknown-prompt "operator paste: > /dr-prd ready for strategy gate"

Subagent Inference (Phase 2)

На miss парсера (confidence: 0) cmd_run.sh передаёт управление в subagent_resolver.sh, который классифицирует текст pane через настраиваемый fallback-chain AI CLI бэкендов:

  • coworker-deepseek (default primary) — coworker ask --provider deepseek --profile code; vendor-neutral OSS CLI.
  • claudeclaude --print --output-format=json; wrapper приходит как {type, result}, resolver повторно парсит .result.
  • codexcodex exec --output-last-message -; best-effort, chain продолжается при parse fail.

Каждый бэкенд имеет 15 с wall-clock budget (DR_ORCH_RESOLVER_TIMEOUT_S), запускается с закрытым FD 3 (bats-harness compatibility), молча пропускается при отсутствии бинаря в $PATH (one-time WARN при первом промахе, дедуп через $STATE_DIR/.warned.<backend>). Lenient JSON extractor обрабатывает raw тело, fenced ```json блоки, и prose-wrapped объекты.

Решение autonomous-vs-escalate живёт в cmd_run.sh, gated на subagent.confidence_threshold (default 0.80). Выход resolver ниже порога (или chain_exhausted) маршрутизируется в escalation sink; на/выше порога — проходит через decision-cooldown gate перед любым autonomous-действием.

Escalation

Два бэкенда подключены в Phase 2 (переопределяется через DR_ORCH_ESCALATION_BACKEND):

  • mock (default) — добавляет JSONL событие в ~/.local/share/dr-orchestrate/escalation.jsonl с frozen-схемой (schema_version, cycle_id, pane_id, prompt_hash, action_suggested, confidence, reason, subagent_model, backend_used, escalation_backend, mock).
  • dev-bot — stub, возвращает exit 99 с WARN до появления реального consumer-сервиса.

Security floor

Каждый tmux send-keys и каждое autonomous-решение проходят фиксированный fail-closed pipeline:

  • Whitelist — разрешены только [a-zA-Z0-9 _-./:=@]. Всё остальное → блок + audit.
  • Escape-block — любой байт 0x1b отвергается.
  • Micro-cooldown — 500 мс gate на каждый send в pane.
  • Decision-cooldown — 60 с gate на каждое autonomous-решение в pane (теперь достигается через resolver path).
  • Flock-safe lock (Phase 2) — flock -n per (pane, kind) на Linux; macOS hosts выдают one-time WARN и работают на non-atomic semantics Phase 1.
  • Violation tracker — 5 нарушений любого типа за час → pane заблокирован на 1 час.

Audit (schema v2)

Phase 2 вводит make_event_v2 рядом с Phase 1 emitter. Schema v2 расширяет v1 6-field event метаданными resolver/escalation:

{
  "schema_version": 2,
  "timestamp": "2026-05-11T08:00:00Z",
  "matched_text_hash": "af86d…",
  "command": "/dr-do",
  "exit_code": 0,
  "duration_ms": 1421,
  "pane_id": "datarim:0.0",
  "confidence": 0.87,
  "subagent_model": "deepseek-chat",
  "backend_used": "coworker-deepseek",
  "escalation_backend": "",
  "stage": "resolve",
  "outcome": "resolved",
  "reason": "explicit slash-command"
}

Hash-only-credentials инвариант сохраняется — сырой текст pane никогда не попадает в лог. Поле reason усечено до 500 символов и grep-redacted для паттернов password=, token=, secret=, credential=, api_key= перед записью.

Конфигурация

# user-config.yaml
subagent:
  fallback_chain: ["coworker-deepseek", "claude", "codex"]
  timeout_s: 15
  confidence_threshold: 0.80

escalation:
  backend: "mock"
  mock_log: ~/.local/share/dr-orchestrate/escalation.jsonl

Уровни автономности

  • Phase 1 — L1 (manual; rule-based confidence; без обучения).
  • Phase 2 — L2 (assisted; multi-backend subagent inference + race-safe cooldown + audit v2).
  • Phase 3 — L4 (план: самообучающиеся правила с 24-часовой re-валидацией).

Soak verdict

В составе плагина — dev-tools/measure-orchestrator-soak.sh, verdict-gate вычисляющий false_escalate_rate = escalated / (resolved + escalated) по событиям audit schema v2. Default порог < 0.15 за последние 48 ч.

Bot-Interaction Interface (v2.5.0+)

С Datarim v2.5.0 / plugin v0.3.0 у оркестратора появляется программный IO surface в дополнение к tmux pane — framework-owned wire contract, через который бот (или любой HTTP-клиент) может отправлять промпты и получать события эскалации/прогресса.

  • OpenAPI 3.1 specplugins/dr-orchestrate/openapi/orchestrator-interface.yaml. Один входящий эндпойнт POST /orchestrator/input, Bearer-авторизация, JSON-тело (session_id, command, ts, опционально meta). Default-ответ — 202 Accepted; sync-shortcut (200 + inline body) только для whitelist-команд (dr-status, dr-help) при заголовке X-Sync-Timeout (hard-cap ≤ 2000 мс).
  • Reference impladnanh/webhook v2.8.3 (Go single binary, MIT, без runtime-зависимостей) + config/hooks.yaml + scripts/orchestrator-input-handler.sh. Адаптер валидирует Bearer против Vault-секрета, проверяет JSON-schema и атомарно пишет ULID-named файл в ~/.local/share/datarim-orchestrate/inbox/. Главный цикл (cmd_run.sh) per cycle забирает oldest-first из inbox и инжектит .command как UNKNOWN_TEXT в существующий semantic-parser → resolver pipeline.
  • Outbound emitter_emit_devbot в escalation_backend.sh заменяет v0.2.x stub. Два бэкенда (переключаются через DR_ORCH_OUTBOUND_BACKEND): callback (default — HMAC-SHA256 + X-Timestamp 300 с replay-window, curl POST на DR_ORCH_ESCALATION_DEVBOT_URL) и redis (opt-in — redis-cli PUBLISH orchestrator-out:{session_id} через DR_ORCH_OUTBOUND_REDIS_URL).
  • Activation gate — при unset DR_ORCH_ESCALATION_DEVBOT_URL _emit_devbot молча return 0 (noop). Rollback = unset переменной. Откат кода не требуется.
  • Network exposure — Tier 1. Reference impl слушает 127.0.0.1:8090 (loopback, single-tenant). Redis-бэкенд использует существующий Tailscale-only listener (без нового Tier 3 surface).
  • Contract-тестыtests/contract/run-schemathesis.sh + CI workflow .github/workflows/dr-orchestrate-contract.yml поднимают reference impl на ephemeral-порту и гоняют schemathesis property-based fuzz против OpenAPI-спеки. dev-tools/check-agent0017-live.sh — ручной pre-activation gate (curl /healthz + smoke POST /prompts) перед выставлением production env.

Не входит в Phase 2

UI Telegram-моста, write-путь самообучающихся правил (Phase 3), реальный dev-bot HTTP endpoint, переписывание Vault secrets_backend.sh, embedding/vector классификация, multi-host SSH aggregation, Docker/Kubernetes orchestration, нативный Windows.