Commit Graph
8 Commits
Author SHA1 Message Date
mayatnikovandClaude Opus 4.7 7a6c874e35 feat(runtime): social layer — intent / templates / chat memory (Phase 5)
Phase 5 of plans/autonomous-survival-bot-prd.md. Make the bot feel
present in chat without ever becoming a command executor.

New: runtime/social/
- intent.js: classifyIntent({text, botName}) returns one of GREETING /
  STATUS_QUESTION / ADDRESSED_BANTER / COMMAND_LIKE / UNSAFE_REQUEST /
  AMBIENT. Unicode-aware word boundaries so cyrillic + latin both work
  ("Привет всем" → GREETING, "build me a tower" → AMBIENT unless
  addressed).
- reply.js: generateReply({intent, speaker, snapshot, diaryTail}) →
  short templated response, or {send: null, escalate: true} for the
  caller to decide whether to spend Pi tokens.
- memory.js: createChatMemory() — per-speaker LRU buffer of recent
  lines; redacts password / api_key / JWT-shaped tokens at append
  time, so the buffer can be safely fed back into any future prompt.
- social.test.js: 12 tests (intent edges, memory eviction, redaction,
  reply routing). npm test now 40/40.

state-store.js additions:
- readDiaryTail(n) — reads the last N lines of today's diary; used by
  status replies.
- writeEscalation({from, request, whyUnsure, wouldHave}) /
  listEscalations() — JSONL log under state/<host>/escalations.jsonl
  for UNSAFE_REQUEST classifications and future operator review.

bot.js: handleChat() now routes through social/intent + social/reply
(replacing the Phase-0 inline regexes), records every line into
chatMemory, and writes an escalation when classifyIntent returns
UNSAFE_REQUEST. Command-like notice + dialog-only behaviour from
Phase 0 are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:30:15 +03:00
ae7b4d89cb feat(runtime): early-game survival curriculum + stone/craft skills (Phase 3) (#15)
Phase 3 of plans/autonomous-survival-bot-prd.md. Gives the bot a
deterministic path from empty inventory through stone-tier tools and
basic storage, without an LLM call per tick.

New:
- runtime/curriculum.js: ordered milestone chooser
  (wood.16 → wood.planks-and-sticks → wood.tools → stone.32 →
   stone.tools → food.basic → storage.chest → shelter.torch). Each
  milestone exposes isDone(inventory, snapshot) and suggest() returning
  a { skillId } plan the scheduler can dispatch via runSkill. isDone
  uses "stage reached" escapes so progress is monotonic — crafting
  planks doesn't bounce the chooser back to "gather 16 logs".
- runtime/skills/gather-stone.js: gather.stone with pickaxe-required
  precondition, blacklist on failed paths, registry-aware matching
  (stone / cobblestone / deepslate / cobbled_deepslate / andesite /
  diorite / granite).
- runtime/skills/craft.js: factory + concrete skills for craft.planks,
  craft.sticks, craft.wooden-axe/-pickaxe/-sword, craft.stone-axe/
  -pickaxe/-sword, craft.furnace, craft.chest, craft.torch (torch
  requires coal or charcoal preflight).

Tests:
- runtime/curriculum.test.js: 14 tests covering chooser ordering,
  per-milestone skill suggestion, inventoryFull threshold, monotonic
  advancement across stage transitions.
- npm test now runs the full suite: 28/28 passing.

Wiring:
- runtime/bot.js: lastSnapshot.curriculum carries the next milestone
  + suggested skill on every tick; lastSnapshot.currentMilestone
  prefers the curriculum title over the planner.md line.
- tui/tui.tsx: milestone line shows the curriculum's suggested skill
  and an [inventory full] flag when isInventoryFull fires.

Reflex.js still calls actions.js directly; wiring the scheduler to
runSkill(plan.skillId, …) lands in Phase 4.

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:23:33 +03:00
4b7541435d feat(runtime): skill substrate + dynamic groups + reference skills (Phase 2) (#14)
Phase 2 of plans/autonomous-survival-bot-prd.md. Establishes the
composable skill contract from PRD §5.2 and ports three reference
skills so future phases can layer survival behaviour on top instead of
adding more ad-hoc branches to reflex.js.

New: runtime/skills/
- index.js: skill registry + runSkill(id, ctx, args) wrapper. Enforces
  preconditions, hard timeout, normalises {ok, code, detail, worldDelta}
  on every result, runs validate() and calls recover() on failure.
  Stable failure codes live in RUNNER_CODES (unknown_skill,
  precondition_failed, timeout, threw, validation_failed, done).
- groups.js: registry-derived item/block sets — logs/planks/sticks/beds
  derived by suffix; foods intersects a curated allowlist with the live
  bot.registry; axes/pickaxes/swords scoped to whatever the connected
  server's item table actually ships. Empty set instead of throwing on
  missing registry, so skills can emit code:"unsupported_version".
- chop-logs.js: gather.logs reference skill (wraps chopNearestTree).
- eat.js: survive.eat (wraps eatBestFood, preconditions check carrying
  edible food from the registry-derived set).
- wander.js: explore.wander (wraps wander).
- contract.test.js + groups.test.js: 14 tests covering precondition
  gating, timeout firing recover(), execute exceptions, validate
  flipping ok→false, dynamic group filtering across mock registries.

package.json: `npm test` runs the new contract + groups suites.
docs/runtime.md: documents the skill contract, runner, dynamic groups
and the reference skills.

Reflex.js still calls actions.js directly — wiring the scheduler to
runSkill() lands in later phases when the survival curriculum kicks in.

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:15:57 +03:00
f301529f42 feat(runtime): observability + no-progress detector (Phase 1) (#13)
Phase 1 of plans/autonomous-survival-bot-prd.md. The bot must always be
able to answer "what am I doing and why am I not doing more?" without
parsing the log stream.

New modules:
- runtime/state.js: pure FSM classifier emitting emergency / working /
  recovering / planning / social / idle from snapshot + reflex context.
- runtime/no-progress.js: sliding-window detector that watches position
  and inventory; when both are unchanged for 60 s+, emits one stable
  reason code from REASONS (waiting_for_day, night_hostile_nearby,
  no_food_source, inventory_full, no_reachable_target, planner_empty,
  awaiting_action_cooldown).
- runtime/viewer.js: optional prismarine-viewer launcher behind
  VIEWER_PORT. Lazy import so the dep is not required by default.

Wiring:
- runtime/bot.js: tick() now computes runtimeState + noProgressReason
  every tick and stamps them on the snapshot along with activeSkill,
  currentMilestone (read from plan.md, cached 30 s), lastResult,
  failuresByCode and lastEscalation.
- runtime/bot.js: dispatchAction records lastResult and lastFailureAt
  for the recovering-state classifier.
- runtime/planner.js: exports isPlannerBusy(), readNextMilestone()
  and planExists() so the runtime can show planning state + current
  milestone without spawning extra Pi calls.
- runtime/config.js: adds VIEWER_PORT support.

TUI:
- tui/tui.tsx: StatusBar gains a state badge, current-skill row,
  milestone row, no-progress reason warning, last-result line with
  ok/fail color, failures-by-class summary and last-escalation age.

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:11:13 +03:00
3310cb320f feat(runtime): survival-bot pivot — MC chat is dialog-only (Phase 0) (#12)
Phase 0 of plans/autonomous-survival-bot-prd.md: change the product
direction from operator-driven remote control to autonomous survival
resident. MC chat is dialog-only for everyone, including
OPERATOR_USERNAMES — commands like come/follow/build/pause/stop are
recorded in the diary but not dispatched. TUI remains the only local
control plane.

Runtime changes:
- Remove operatorGoalReflex from reflex.js (the come-here chat command).
- Replace handleOperatorChat in bot.js with a dialog-only handleChat
  that answers greetings/status questions and records command-like
  verbs (en+ru) without dispatching them.
- Default MC_VERSION to "auto" in runtime/config.js; mineflayer
  receives `false` to trigger version auto-detection.
- Update auto-escalation prompt's reflex chain summary.

Docs:
- AGENTS.md: product pivot notice up top; chat-driven scope-trust is
  flagged as legacy/Pi-only.
- README.md / docs/runtime.md: replace operator-chat command list with
  dialog-only description; update reflex chain summary.
- docs/roadmap.md: Phase 2/3 marked superseded by the PRD where they
  assumed chat-driven control.

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:01:26 +03:00
7797dd3d5a feat(runtime): fully autonomous self-healing — no operator approval (#10)
Operator feedback: "бот должен быть полностью автономным — сам себя
улучшать и чинить, в этом и есть смысл; все что я вижу пока что он
стоит на месте и кидает proposals на каждый чих — это кардинально не
то что я хочу". Acted on:

1. Trigger filter — proposals only on real bugs.

   runtime/bot.js classifies failure detail into bug / timeout /
   feature-gap / other. The 5-in-a-row trigger fires only when the run
   contains a bug (TypeError / Cannot read / is not defined …) OR is
   entirely timeouts on the same operation. Feature gaps like "no
   reachable log within 32 blocks", "no food in inventory", "no bed in
   range", "no target in reach" are SKIPPED — the reflex layer routes
   around them (noTreesUntil → wander, etc). The LLM has no business
   patching code for missing inventory.

   Threshold raised 3 → 5 in a row. Cooldown unchanged (30 min).

2. Auto-apply, no operator-in-the-loop.

   New runtime/auto-improve.js polls proposals/ every 2s. When it sees
   a new .md and 10s have passed since first sighting (debounce),
   spawns scripts/auto-patch.js detached.

   New scripts/auto-patch.js: refuses on dirty tree, moves proposal
   pending → approved/, branches `auto/<slug>` off main, runs `pi -p`
   with 10-min timeout. If Pi committed AND every changed file is
   under runtime/ → cherry-picks onto main. Otherwise discards the
   branch. No push, no PR. Audit trail in state/<host>/proposals/approved/.

   Rate limit: 15-min cooldown between finished runs + 4/hour hard cap.

3. Auto-rollback on bad patches.

   runtime/supervisor.js: when MAX_RESTARTS_PER_MINUTE is exceeded
   AND `git log -1 HEAD` is younger than 15 min AND HEAD touched
   runtime/, runs `git reset --hard HEAD~1`. Up to MAX_ROLLBACKS=3
   lifetime, then exits 1 for manual investigation. Restart counters
   are reset after a successful rollback so the next attempt isn't
   immediately killed.

4. current-task.json slim.

   No longer stores the full perception snapshot (was ~3 KB per write
   × every action). Position only — sufficient as a resume anchor.
   Slim snapshot still goes into the proposal markdown for context.

docs/runtime.md — rewrote the self-improvement section: full flow
diagram, classification rules, all rate-limit knobs, manual escape
hatches kept but documented as rarely-needed.

Also cleared 5 stale proposals from previous smoke tests so the first
production run isn't burning Pi tokens on stale bugs that have since
been fixed.

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:56:02 +03:00
445524b34d docs(runtime): reflect live reflex bodies + operator chat + self-improvement loop (#7)
Updates docs/runtime.md and README.md to match what's actually shipped:
  - reflex chain priorities and what each body now dispatches
  - operator chat command list (status, come, pause, resume, stop)
  - automatic + manual Pi escalation paths and the no-code-change rule
  - the full self-improvement loop end-to-end (detector → TUI approval
    → propose:apply → supervisor restart) with the rationale for the
    manual propose:apply step
  - new state files layout (proposals/, proposals/approved/, etc.)
  - supervisor.js + bot:bare script flags

No code changes.

Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:22:38 +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