Skip to content

feat(queen-doctor): autonomous Queen↔Doctor loop over canonical bus#506

Open
gHashTag wants to merge 1 commit intomainfrom
bee/queen-doctor-autoloop
Open

feat(queen-doctor): autonomous Queen↔Doctor loop over canonical bus#506
gHashTag wants to merge 1 commit intomainfrom
bee/queen-doctor-autoloop

Conversation

@gHashTag
Copy link
Copy Markdown
Owner

@gHashTag gHashTag commented May 3, 2026

Что это

Реальная автономная петля Королева ↔ Доктор через канонический bus
trios-server. Без человека-толкача между приказом и отчётом.

   ┌─ Queen ──────┐  queen/order   ┌─ trios-server ─┐  BusEvent::QueenOrder
   │ trios-queen- │ ─────────────▶ │  /operator WS  │ ────────────────▶ Doctor
   │ loop (new)   │                │   /ws WS       │
   │              │ ◀───────────── │                │ ◀────────────────  Doctor
   └──────────────┘  BusEvent::    └────────────────┘  doctor/report
                     DoctorReport

Изменения

Component File Status
Bus events + RPC crates/trios-server/src/ws_handler.rs +196 lines, 4 new tests
Doctor daemon crates/trios-doctor/src/doctor_loop.rs (new bin trios-doctor-loop) +289 lines
Queen daemon crates/trios-queen-loop/ (new crate) +438 lines
E2E smoke crates/trios-queen-loop/tests-e2e/smoke_queen_doctor_loop.py +100 lines

Server (ws_handler.rs)

  • +BusEvent::QueenOrder { order_id, action, target_agent, params, ts }
  • +BusEvent::DoctorReport { order_id, agent_id, status, summary, diagnosis, ts }
  • +RPC methods"queen/order", "doctor/report"
  • +pub async fn queen_order_publish / doctor_report_publish — broadcast helpers
  • +4 unit tests доказывают broadcast roundtrip и валидацию обязательных полей

Doctor (crates/trios-doctor)

Новый бинарь trios-doctor-loop:

  • подписывается на /ws, фильтрует QueenOrder где target_agent="doctor"
  • для doctor scan|quick|heal зовёт настоящий Doctor::run_all()
    WorkspaceDiagnosis, мапит Red/Yellow/Green в статус отчёта
  • отправляет doctor/report обратно с тем же order_id
  • auto-reconnect с TRIOS_DOCTOR_RECONNECT_SECS (default 5s)

Queen (crates/trios-queen-loop)

Новый крейт-демон (workspace member):

  • конект на ws://127.0.0.1:9005/operator?token=$TRIOS_OPERATOR_TOKEN
  • читает .trinity/queen/{policy,actions}.json из рабочей директории
  • выбирает действия level ≤ policy.max_auto_level (default 3) и
    начинающиеся с doctor
  • детерминированный пик: (epoch_secs / tick) % candidates.len() — без
    персистентного состояния
  • отслеживает order_id в VecDeque<64>, коррелирует входящие DoctorReport
  • tick TRIOS_QUEEN_TICK_SECS (default 60s)

Verification (всё зелёное)

cargo check  -p trios-server -p trios-doctor -p trios-queen-loop  → ✅
cargo build  --bins (server, doctor, doctor-loop, queen-loop)     → ✅
cargo test   -p trios-server  --bins ws_handler                   → 16/16 ✅
cargo test   -p trios-doctor  --lib                               →  9/9  ✅
python3 crates/trios-queen-loop/tests-e2e/smoke_queen_doctor_loop.py

E2E smoke против работающего сервера на 9005:

[queen]  sent queen/order
[queen]  full event: {"data":{"action":"doctor scan","order_id":"f1b7991e-…",
                      "target_agent":"doctor","ts":1777839046},"type":"QueenOrder"}
[doctor] full event: {"data":{"action":"doctor scan","order_id":"f1b7991e-…",
                      "target_agent":"doctor","ts":1777839046},"type":"QueenOrder"}
[doctor] queen_order=f1b7991e-… → sent doctor/report
[queen]  full event: {"data":{"agent_id":"doctor","order_id":"f1b7991e-…",
                      "status":"green","summary":"smoke-test ack",
                      "ts":1777839046},"type":"DoctorReport"}
RESULT: GREEN — Queen↔Doctor loop closed end-to-end through real WS bus

order_id корректно коррелирует между исходящим приказом Королевы и
входящим отчётом Доктора.

Constitutional compliance · φ² + φ⁻² = 3

  • L1 — pure Rust, ни одного .sh
  • L11 — каждый order несёт soul (default SCARABS)
  • L14Agent: SCARABS trailer присутствует
  • L21 — bus append-only, никаких ретроактивных мутаций
  • L24 — общение только через канонический /ws и /operator,
    никаких sibling-сокетов

Как поднять

# 1. сервер
cargo run -p trios-server --bin trios-server &

# 2. доктор-демон
TRIOS_DOCTOR_WS_URL=ws://127.0.0.1:9005/ws \
  cargo run -p trios-doctor --bin trios-doctor-loop &

# 3. королева-демон
TRIOS_QUEEN_WS_URL=ws://127.0.0.1:9005/operator \
TRIOS_OPERATOR_TOKEN=<token-from-server-log> \
TRIOS_QUEEN_TICK_SECS=60 \
  cargo run -p trios-queen-loop --bin trios-queen-loop

С этого момента петля автономна: Королева раз в минуту шлёт doctor scan,
Доктор отчитывается, Королева логирует и шлёт следующий приказ.


Soul: Scarab Smith
Agent: SCARABS

Closes the human-out-of-the-loop circuit between the Queen daemon and
the Doctor daemon by extending the existing trios-server WS bus with two
new BusEvent variants and a small pair of long-running clients.

Loop:

    Queen  --queen/order-->  trios-server  --BusEvent::QueenOrder-->  Doctor
    Doctor --doctor/report--> trios-server --BusEvent::DoctorReport--> Queen

Server (`crates/trios-server/src/ws_handler.rs`)
  • +BusEvent::QueenOrder   { order_id, action, target_agent, params, ts }
  • +BusEvent::DoctorReport { order_id, agent_id, status, summary,
                              diagnosis, ts }
  • +RPC methods            "queen/order", "doctor/report"
  • +helpers                queen_order_publish, doctor_report_publish
  • +4 unit tests           (broadcast roundtrip, missing-field rejection)

Doctor (`crates/trios-doctor/src/doctor_loop.rs`, new bin trios-doctor-loop)
  • Subscribes to /ws, filters QueenOrder where target_agent="doctor".
  • For "doctor scan" / "doctor quick" / "doctor heal" calls the real
    `Doctor::run_all()` and maps Red/Yellow/Green to the report status.
  • Auto-reconnect with TRIOS_DOCTOR_RECONNECT_SECS (default 5).

Queen (`crates/trios-queen-loop`, new crate)
  • Connects to /operator with $TRIOS_OPERATOR_TOKEN.
  • Reads `.trinity/queen/{policy,actions}.json` from workspace root.
  • Filters actions level <= policy.max_auto_level (default 3) and
    starting with "doctor ".
  • Picks deterministically: (epoch_secs / tick) % candidates.len().
  • Sends queen/order, tracks order_id in VecDeque<64>, correlates the
    matching DoctorReport.
  • Tick interval TRIOS_QUEEN_TICK_SECS (default 60s).

Verification (`crates/trios-queen-loop/tests-e2e/smoke_queen_doctor_loop.py`)
  Live end-to-end smoke against a running trios-server confirms both
  halves of the loop close — order_id correlates exactly between the
  outgoing Queen frame and the incoming Doctor report:

    [doctor] queen_order=f1b7991e-… → sent doctor/report
    [queen]  DoctorReport: status=green, order_id=f1b7991e-…
    RESULT: GREEN — Queen↔Doctor loop closed end-to-end via real WS bus

Test runs:
  • cargo check  -p trios-server -p trios-doctor -p trios-queen-loop  → green
  • cargo build --bins (all three)                                    → green
  • cargo test   -p trios-server  --bins ws_handler                   → 16/16
  • cargo test   -p trios-doctor  --lib                               →  9/9
  • python3 smoke_queen_doctor_loop.py                                → GREEN

Constitutional anchors: φ² + φ⁻² = 3
  L1   no .sh files (pure Rust)
  L11  every order carries a soul field, default "SCARABS"
  L14  Agent trailer present
  L21  broadcast bus is append-only
  L24  agents speak only via the canonical bus

Soul: Scarab Smith
Agent: SCARABS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant