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.
## 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)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Brings the hybrid runtime from stub-reflexes to real Mineflayer-driven behavior.
Smoke test (live, play.xmatic.team)
This confirms: real actions trigger, hard timeouts unblock the loop when pathfinder gets stuck, busy-state prevents action overlap.
Test plan
Next PRs
🤖 Generated with Claude Code