feat(runtime): live reflex bodies + auto-escalation + operator chat #5

Merged
halofourteen merged 1 commits from feat/reflex-bodies into main 2026-05-25 16:11:53 +03:00
halofourteen commented 2026-05-25 16:11:46 +03:00 (Migrated from github.com)

Summary

Brings the hybrid runtime from stub-reflexes to real Mineflayer-driven behavior.

  • `runtime/actions.js` — async primitives with hard timeouts and `{ok, detail}` returns: `attackNearest`, `fleeFrom`, `eatBestFood`, `sleepInBed`, `goTo`. Pathfinder plugin is lazy-loaded per bot.
  • `runtime/reflex.js` — bodies dispatch real actions via `ctx.dispatch`. Priority chain: `operator-goal > defend > eat > sleep > idle`. Returns `skipped` on `ctx.busy` so dispatching ticks don't pollute the escalation counter.
  • `runtime/bot.js`:
    • `ctx.dispatch` — fire-and-forget with busy gate + `onComplete` hook, so reflexes can ship a goal description and bind chat-replies to action results without await chains in the tick path.
    • Auto-escalation: after 20 consecutive noop ticks (~1 min at tick=3s), `askPi` fires with the current JSON snapshot. 10-min cooldown.
    • Operator chat: messages prefixed with the bot's name from `OPERATOR_USERNAMES` are parsed as commands. Today: `status`, `pause`, `resume`, `stop`, `come`. Death clears any pending operator goal.

Smoke test (live, play.xmatic.team)

  • Bot connected, AuthMe `/login` sent, spawned at `(623, 85, 95)`.
  • t+1.9s: `sleepReflex` decided night → no bed in range → declined cleanly.
  • t+21s: zombie entered 12 m + bot HP/hostile heuristic triggered `fleeFrom(zombie) → 615,85,82`.
  • t+51s: pathfinder couldn't path through dark_forest leaves to that target → hard 30 s timeout fired (exactly what the wrapper exists for).
  • Next tick: `sleepReflex` retried after cooldown, declined again. Loop healthy.

This confirms: real actions trigger, hard timeouts unblock the loop when pathfinder gets stuck, busy-state prevents action overlap.

Test plan

  • Live: bot defends itself against a zombie within reach (needs `bot.attack` to actually land — requires `bot.modes`-style entity loop in a follow-up).
  • Live: bot eats when food drops below 16 (needs food in inventory).
  • Live: bot sleeps in a placed bed at night (needs a bed near spawn).
  • Live: operator says `pepa_bot come` and bot walks to operator's position.
  • Live: auto-escalation fires after 1 min of idle. (Manual test: keep area mob-free, wait.)

Next PRs

  • Self-improvement: proposals/*.md → operator approval → Pi-driven patch → hot reload.
  • Persisted current-task.json + diary writes (so a restart resumes).
  • `follow me` (continuous operator follow).

🤖 Generated with Claude Code

## Summary Brings the hybrid runtime from stub-reflexes to real Mineflayer-driven behavior. - **\`runtime/actions.js\`** — async primitives with hard timeouts and \`{ok, detail}\` returns: \`attackNearest\`, \`fleeFrom\`, \`eatBestFood\`, \`sleepInBed\`, \`goTo\`. Pathfinder plugin is lazy-loaded per bot. - **\`runtime/reflex.js\`** — bodies dispatch real actions via \`ctx.dispatch\`. Priority chain: \`operator-goal > defend > eat > sleep > idle\`. Returns \`skipped\` on \`ctx.busy\` so dispatching ticks don't pollute the escalation counter. - **\`runtime/bot.js\`**: - \`ctx.dispatch\` — fire-and-forget with busy gate + \`onComplete\` hook, so reflexes can ship a goal description and bind chat-replies to action results without await chains in the tick path. - Auto-escalation: after 20 consecutive noop ticks (~1 min at tick=3s), \`askPi\` fires with the current JSON snapshot. 10-min cooldown. - Operator chat: messages prefixed with the bot's name from \`OPERATOR_USERNAMES\` are parsed as commands. Today: \`status\`, \`pause\`, \`resume\`, \`stop\`, \`come\`. Death clears any pending operator goal. ## Smoke test (live, play.xmatic.team) - Bot connected, AuthMe \`/login\` sent, spawned at \`(623, 85, 95)\`. - t+1.9s: \`sleepReflex\` decided night → no bed in range → declined cleanly. - t+21s: zombie entered 12 m + bot HP/hostile heuristic triggered \`fleeFrom(zombie) → 615,85,82\`. - t+51s: pathfinder couldn't path through dark_forest leaves to that target → hard 30 s timeout fired (exactly what the wrapper exists for). - Next tick: \`sleepReflex\` retried after cooldown, declined again. Loop healthy. This confirms: real actions trigger, hard timeouts unblock the loop when pathfinder gets stuck, busy-state prevents action overlap. ## Test plan - [ ] Live: bot defends itself against a zombie within reach (needs \`bot.attack\` to actually land — requires \`bot.modes\`-style entity loop in a follow-up). - [ ] Live: bot eats when food drops below 16 (needs food in inventory). - [ ] Live: bot sleeps in a placed bed at night (needs a bed near spawn). - [ ] Live: operator says \`pepa_bot come\` and bot walks to operator's position. - [ ] Live: auto-escalation fires after 1 min of idle. (Manual test: keep area mob-free, wait.) ## Next PRs - Self-improvement: proposals/*.md → operator approval → Pi-driven patch → hot reload. - Persisted current-task.json + diary writes (so a restart resumes). - \`follow me\` (continuous operator follow). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.