11 Commits
Author SHA1 Message Date
e84148d189 v0.2.0-rc.2: P0 hardening — Pi headless, test state isolation, advice fixes (#21)
P0 (correctness):

1. PEPA_HEADLESS=1 guard in extensions/mineflayer-bridge.ts. When `pi -p`
   spawns a subprocess (banter, coach, planner, reflect, auto-patch), the
   bridge no longer attempts a second MC connect — the hybrid runtime
   already owns the nickname. runtime/pi-bridge.js sets the env var on
   every spawn. Root cause of the "two pepa_bot's racing for the slot"
   bug seen in reply-pi stderr.

2. Test state isolation in runtime/config.js. When running under the node
   test runner (detected via execArgv/argv) — or when PEPA_STATE_DIR is
   set — stateDir redirects to /tmp/pepa-test-state-<pid>/. log.js,
   scenario-memory, world-journal, and knowledge.db all follow.
   `npm test` no longer pollutes live scenarios.jsonl, world-journal.jsonl,
   or daily log files. Verified empirically: post-fix run added 0 test
   rows to the live scenarios file. Cleaned ~550 historical test rows
   from live state in the same change.

3. defendReflex outcome reporting (runtime/reflex.js). Previously a
   creeper-rule override marked the lesson succeeded=false BEFORE the
   flee skill returned. Now dispatchDefendFlee accepts {lessonId} and
   the onComplete fires reportAdviceOutcome with the actual flee result.

4. Mode-name → skill-id translation in runtime/coach/advice.js. Pi-coach
   occasionally returns prefer_skill values that are mode names
   ("night_shelter", "self_preservation", "hunger"). normalisePreferSkill
   maps these to SAFE_OVERRIDES entries before dispatch. Also handles
   "tunnel-out", "survive_flee", "survive flee" shapes.

New behavior:

5. Self-reflection loop (runtime/coach/reflect.js). Every 30 min, the
   bot asks Pi: "Are you making progress, or stuck in a loop? What
   should you do differently?" Pi answers with a verdict
   (progress/loop/recovering/idle/emergency), summary, next-action, and
   0-N new lessons. The reflection is written to
   state/<host>/reflections/<ts>.md and lessons land in the DB with
   source="pi-reflect". Rate-limited to 2 calls/hour. Wired through
   bot.js with the existing askPi + lastSnapshot accessor.

Tests: 246/246 green (+9 new: 6 advice mode-name + 4 reflect).

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 14:10:28 +03:00
1e3b36a9a1 feat(runtime): hybrid script reflex + Ink TUI + Pi-on-demand escalation (#4)
* fix(mindcraft-skills): hard timeout on every skill call

mc_avoid_enemies (and 7 other tools) wrapped only in safeCall without a
withTimeout. When mindcraft's underlying pathfinder/pvp goal couldn't be
satisfied, the call never resolved — the Pi tick loop blocked forever.
Observed live: mc_avoid_enemies pending >10 minutes after one mc_observe.

safeCall now takes timeoutMs (default 30s) and wraps withTimeout itself,
so every tool gets a hard ceiling. Per-tool overrides:
  - goToPosition / goToNearestBlock: 120s / 90s (unchanged from before)
  - defendSelf / avoidEnemies: 45s
  - stay: secs*1000 + 10s
  - craft / consume / pickup / place: 30s
  - equip: 15s
collectBlock still uses its bespoke per-iter 75s loop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(runtime): script-driven reflex daemon + Ink TUI dashboard

Pure-Pi runtime had three failure modes in practice:
  - slow: 20-60s per decision because LLM was in the hot path
  - expensive: every tick (defend, eat, idle) paid for a reasoning pass
  - invisible: required tmux capture-pane to know what the bot was doing

New runtime/ layer is a long-running Node daemon that owns the MC
connection, ticks a priority-ordered reflex chain (defend > eat > sleep
> idle) with NO LLM in the hot path, and exposes status + commands over
a Unix-socket IPC. tui/ is an Ink dashboard that attaches over IPC and
can detach freely — multiple TUI clients can connect at once.

Pi/Codex are still available, but as on-demand escalation: TUI hotkey
'a' spawns `pi -p "<prompt>"` as a subprocess and streams stdout into
the dashboard. The self-improvement loop (proposals → operator approval
→ Pi-driven patch → hot reload) is documented in docs/runtime.md but
not yet wired.

Reflex bodies are stubs today — they log decisions but don't drive
Mineflayer actions yet. The priority chain, IPC contract, and TUI are
fully working; subsequent commits will fill in defend/eat/sleep bodies
and wire automatic escalation.

Run with `npm run bot` + `npm run tui`. Pi-only fallback stays at
`npm run agent`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:04:48 +03:00
mayatnikovandClaude Opus 4.7 68f59dfa4c feat(recovery): death handler + auto-defend reflex + bulk-collect rework + mc_stay shim
Four targeted fixes for issues observed during the live autonomous test:

1. **bot.modes shim** (extensions/lib/mcdata.js)
   Mindcraft skills.* call bot.modes.pause('cowardice') in 7+ places.
   `mineflayer-modes` does not exist on npm — it's internal to Mindcraft.
   attachPluginsAndInit now installs a no-op shim so skills.stay() /
   .consume() / .defendSelf() etc. stop crashing with "pause undefined".

2. **Death + respawn handlers** (extensions/mineflayer-bridge.ts)
   Subscribe to bot 'death' event: append diary line with position,
   clear current-task.json so Pi doesn't resume a stale task referencing
   inventory that no longer exists.
   On 'spawn' within 5s of death: log the new respawn position to diary.
   Live test had bot killed twice by zombies at night; the next Pi
   prompt was unable to recover. With this it's now an explicit diary
   line + clean task slate.

3. **Auto-defend reflex tick** (extensions/mineflayer-bridge.ts)
   New setInterval(2s) that, when bot.health < 18 AND a hostile mob
   (zombie/skeleton/creeper/spider/etc.) is within 6 blocks AND no
   active world task, fires `bot.pvp.attack(nearest)` in the background.
   No LLM call needed for instant self-defense — saves tokens and reacts
   on mineflayer timescale (sub-second) rather than Pi loop timescale
   (~10s+ to reason and dispatch). Throttled to once per 4s.

4. **mc_collect_block bulk rework** (extensions/mindcraft-skills.ts)
   Live test showed count=1 succeeds in ~25s but count=8 hangs past
   270s with identical blocks in range. Upstream collectBlock plugin
   appears to drift on its block cache after the first dig in dense
   terrain. Loop single-block collects in-tool instead (75s per iter,
   re-pathfind on each iteration). Track per-iter success/failure,
   abort after 3 consecutive failures, return aggregate count to the
   agent so it can adapt instead of seeing a single failure.

Smoke test: both extensions load, bot connects, perception confirms
hostiles nearby and daylight safety check. No syntax/runtime errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:06:37 +03:00
mayatnikovandClaude Opus 4.7 a323bdea85 fix(mindcraft-skills): scale collectBlock timeout with count
Live test showed count=1 succeeds in ~25s but count=8 timed out at 90s
because gathering 8 logs naturally takes ~200s of pathing + dig + pickup
across the area. Fixed 90s ceiling was too tight for legitimate bulk
collection.

Scale timeout linearly: 30s overhead + 30s per requested block, capped
at 600s. count=1 → 60s, count=4 → 150s, count=8 → 270s, count=20 → 630s
(capped at 600). Catches real hangs (wrong name, unreachable) without
killing legitimate long collections in dense forest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:42:07 +03:00
mayatnikovandClaude Opus 4.7 f46272d8c4 fix(mindcraft-skills): hard timeout on collectBlock/goToPosition/goToNearestBlock
Mineflayer's collectBlock plugin and pathfinder can hang indefinitely when:
- the requested block name doesn't match anything in range (e.g. asking for
  "oak_log" when the only nearby logs are "dark_oak_log"),
- pathfinder cannot reach the goal but doesn't return a clean noPath,
- a path computation enters an infinite-search state in dense terrain.

This blocks the entire Pi tool loop — observed in a live test where
mc_collect_block("oak_log", 4) ran for 8+ minutes without ever returning,
leaving Pi unable to respond to chat or do anything else.

Add a 90s timeout for collectBlock/goToNearestBlock and 120s for goToPosition.
On timeout the tool throws a descriptive error so the agent learns to retry
with a different block name or position rather than waiting forever.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:37:14 +03:00
mayatnikovandClaude Opus 4.7 3e61b87f19 feat(perception): vendor mindcraft skills/world library + Pi tool wrappers
The bot was acting blind: it knew its own coordinates but nothing about
what was around it. mc_goto's over-strict safety guards refused every
real path. mc_dig was too low-level to drive a coherent farming loop.
The result: 4+ hours of "trying" with zero physical achievement.

This commit reframes the bridge around a perceive→decide→act loop using
proven primitives from Mindcraft (github.com/kolbytn/mindcraft, MIT —
LICENSE-MINDCRAFT vendored beside the library files).

Changes:

- extensions/lib/  (new, vendored from Mindcraft with attribution)
  - world.js  (431 LoC) — 21 perception functions: getNearbyBlockTypes,
    getNearbyEntities, getInventoryCounts, getNearestBlock, getPosition,
    getBiomeName, etc.
  - skills.js (2093 LoC) — 30+ action primitives: collectBlock, placeBlock,
    goToPosition, goToNearestBlock, craftRecipe, equip, consume,
    defendSelf, avoidEnemies, pickupNearbyItems, stay, etc.
  - mcdata.js (~600 LoC) — Mindcraft's mc-data adapter. Imports patched
    to local paths; mineflayer-auto-eat removed (our installed 5.x has
    a divergent API; skills.consume() falls back to bot.consume()).
    Added attachPluginsAndInit(bot) export so mineflayer-bridge.ts can
    wire plugins onto its externally-created bot.
  - settings.js — minimal stub with farmer-bot defaults.

- extensions/mindcraft-skills.ts (new, 406 LoC) — Pi extension registering
  15 high-level tools on top of the vendored library:
  - Perception: mc_observe, mc_inventory, mc_nearby_blocks, mc_nearby_entities
  - Action: mc_collect_block, mc_place_block, mc_go_to, mc_go_to_block,
    mc_craft, mc_equip, mc_consume, mc_defend_self, mc_avoid_enemies,
    mc_stay, mc_pickup_nearby
  ES modules from extensions/lib/ are loaded via dynamic import() at
  extension init so the cross-extension require()-race resolves cleanly.

- extensions/mineflayer-bridge.ts
  - Expose the live Mineflayer bot on globalThis.__pepaPiBot so the
    mindcraft-skills extension can use it (set on connect, cleared on
    error/end/manual disconnect).
  - Call attachPluginsAndInit(nextBot) right after createBot to load
    pathfinder, pvp, collectblock, armorManager and prime
    minecraft-data once login completes.

- package.json — new runtime deps: minecraft-data, vec3,
  mineflayer-pvp, prismarine-item.

- AGENTS.md — new "Perception → decision → action" section before
  "Your tools right now" with full tool catalog and a deprecation
  note for the broken mc_goto / mc_build_pyramid_5x5 / low-level
  mc_dig from the old bridge.

Smoke test (medium thinking): bot called mc_observe and received a
real JSON snapshot — nearbyBlocks listed coal_ore, oak_log, water,
sand; nearbyEntityTypes listed creeper, zombie, pillager, skeleton.
The bot can finally see what it could not see this morning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:24:23 +03:00
mayatnikov b778eaa2fb pre codex 2026-05-25 12:51:14 +03:00
mayatnikov ef92553af6 Wire scope-trusted operators 2026-05-25 11:57:41 +03:00
mayatnikov ce41bf6be6 Add live presence and escalation loop 2026-05-25 11:21:47 +03:00
mayatnikov 945b9733a7 Bootstrap Mineflayer bridge scaffold 2026-05-25 10:35:23 +03:00
mayatnikovandClaude Opus 4.7 3a025c05ad chore: bootstrap pepa-pi-bot scaffold
Initial seed for an autonomous, self-extending Minecraft player powered by
Pi (pi.dev) and Mineflayer.

Includes README, AGENTS.md mandate, .env.example, MIT LICENSE, package.json
with mineflayer + dotenv, and empty skills/ extensions/ prompts/ dirs for
the agent to grow into.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 09:50:17 +03:00