Files
pepa-pi-bot/dev/v0.3.0/PLAN.md
T
mayatnikovandClaude Opus 4.7 fcfa2277ba v0.3.0-rc.1: live skill registry + fast advisor scaffold
Roots out the v0.2.x failure mode: Pi-extracted lessons routinely named
hallucinated skill ids (relocate.surface, choose.safe.surface,
survive.shelter, gather.visible_log, …). All 47 Pi-lessons in the live DB
had applied_count=0 because normalisePreferSkill couldn't find them.

Fix:
1. runtime/skill-registry.js — single source of truth derived from
   skills/index.js. Exports listSkillIds, isRegistered, and a
   prompt-ready block (skillRegistryPrompt) grouped by namespace.
2. Pi prompts (coach/postmortem, coach/reflect) embed the live registry
   with a "USE ONLY THESE, never invent" instruction. Lessons are
   filtered at write-time too — anything not in the registry and not a
   known mode name gets dropped.
3. coach/advice.js — normalisePreferSkill now returns null for unknown
   ids, hardening consult() against any hallucinations that slip
   through. Warn-logged for visibility.

Also lays the LLM substrate for the rest of v0.3.0:

- runtime/llm/provider.js — OpenAI-compatible chat client. Configured
  via PEPA_FAST_LLM_{BASE_URL,API_KEY,MODEL,TIMEOUT_MS}. Safe no-op
  unless API_KEY is set. Supports JSON-mode.
- runtime/coach/fast-advisor.js — tactical advisor tier (scaffold).
  Exposes advise() that asks the fast LLM what to do RIGHT NOW when
  the reflex is wedged/stuck. Rejects hallucinated skill ids using the
  registry. Rate-limited 6/h, 30s cooldown. Not auto-triggered yet —
  wired into reflex in rc.3 (awareness layer).

Tests: 279 green (+24 vs rc.3): 5 registry, 9 provider, 10 advisor.

See dev/v0.3.0/PLAN.md for the full iteration design (manifesto needs
ladder, event-driven awareness, skill pre-emption) and STATUS.md for
shipped/pending tracking.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 17:39:43 +03:00

9.6 KiB
Raw Blame History

pepa v0.3.0 — Maslow + Awareness

Concept: needs-based hierarchical agent with real-time event awareness and a fast LLM tactical advisor. Pi (CLI) stays for slow deep analytics (postmortem, reflection). A second, fast LLM tier (TimeWeb / OpenAI- compatible) handles "what to do right now" decisions when the reflex detects wedged/stuck/changed environment.

This is a major behavioural rewrite over v0.2.x:

  • v0.2.x had a flat reflex chain (modes → defend → eat → sleep → curriculum → idle) — curriculum was just "next mode". The bot had no internal concept of "do I have a pickaxe?" let alone "do I have a shelter?" Lessons from Pi were hallucinated skill names (47/47 Pi-extracted lessons applied_count=0 as of v0.2.0-rc.3).
  • v0.3.0 introduces a needs ladder (Maslow-like) that drives the bot's intent end-to-end, an awareness layer that reacts to env changes within ~100ms instead of waiting for the next tick boundary, and a fast LLM tier that closes the loop when the bot is stuck.

Concept terms

This pattern is called variously in the AI literature:

  • Hierarchical Task Network (HTN) planning — Voyager uses this
  • Needs-based / utility AI — game-AI mainstream
  • BDI agent (Beliefs-Desires-Intentions) — academic AI
  • Subsumption architecture (Brooks) — reactive layers preempt deliberative layers when conditions trigger

Pepa v0.3.0 is essentially Maslow-stack curriculum + Brooks-style preemption + dual-tier LLM (fast tactical + slow analytical).

Manifesto / Needs ladder

L0  alive          HP>5, не тонет, не горит, не падает с фатальной высоты
L1  food           ≥6 насыщения (готов кушать на месте)
L2  tools_wood     wooden_pickaxe + wooden_axe + wooden_sword
L3  shelter_basic  4 стены + крыша + кровать в радиусе 8 от спавн-base
L4  tools_stone    stone_pickaxe + stone_axe + stone_sword
L5  armor_basic    хотя бы один кусок (predпочтительно нагрудник)
L6  food_security  ≥16 еды + источник (ферма / стая коров рядом)
L7  tools_iron     iron_pickaxe + iron_axe + iron_sword
L8  armor_iron     полный iron set
L9  village_seed   2+ постройки, забор/оградка, базовая ферма
L10 village_full   глобальная цель (ферма + дом + сосед-NPC мечта)

На каждом тике reflex выбирает самую нижнюю неудовлетворённую нужду. Эта нужда становится активной. Curriculum.next() и Pi-coach подсказки дальше выбираются внутри активной нужды. Если нужда сменилась (например, HP упало → L0 проснулся), текущий skill прерывается.

v0.3.0 release plan (3 rc)

rc.1 — Skill registry hardening + Fast advisor scaffold

Цель: убрать главную проблему v0.2.x — Pi инвентит skill names. Не вводим манифест ещё, но строим инфраструктуру для него.

  • runtime/skill-registry.js — exported listSkillIds(), isRegistered(id), skillRegistryPrompt() (готовый блок текста для LLM-промпта со списком валидных id, по группам)
  • Все Pi-промпты (coach/postmortem.js, coach/reflect.js) передают реестр в system prompt
  • runtime/coach/advice.js: normalisePreferSkill строго отбрасывает всё, что не в реестре (raise log, не дрейфит на fuzzy)
  • runtime/llm/provider.js — OpenAI-совместимый клиент, конфигурируется через env (PEPA_FAST_LLM_BASE_URL, _API_KEY, _MODEL); graceful fallback "no-op" если env не задан (бот не падает)
  • runtime/coach/fast-advisor.js — функция advise({snapshot, reason}) с rate-limit (макс. 6 вызовов/час), таймаут 8с, JSON-парсинг ответа через тот же extractJson() что у Pi. Пока не подключаем к reflex — scaffold + тесты
  • Тесты для каждого нового модуля + регрессионный тест: advice.test.js проверяет что hallucinated relocate.surface falls through (никакой override)
  • Минимум 270+ зелёных тестов

rc.2 — Manifesto / Needs ladder + curriculum integration

Цель: bot acts toward concrete needs, not toward "explore further".

  • runtime/manifesto/needs.js — каталог 11 нужд, каждая со схемой:
    { id, level, detect(snapshot) → boolean satisfied, prefer_skill_for_pursuit, ... }
    
  • runtime/manifesto/state.jspickActiveNeed(snapshot) возвращает самую нижнюю неудовлетворённую. Кеширует на 5с.
  • runtime/reflex.js:
    • В curriculumReflex сначала activeNeed = pickActiveNeed(...)
    • Skill подбирается в первую очередь по activeNeed.prefer_skill_for_pursuit
    • Fallback на curriculum.next() только если нужда не дала однозначного skill
  • runtime/coach/advice.js: consult() теперь принимает activeNeed и отбрасывает lessons чьи trigger_situation противоречит текущей нужде (например, "избегай ночью гулять" не применяется когда L0=alive в опасности)
  • Pi-промпты (postmortem, reflect) получают currentNeed: "L2 tools_wood" и просят Pi дать совет именно для этого уровня
  • Новый персонаж reflex hook: при смене activeNeed бот произносит в чате "пора заняться X" (Russian narration tying into chatter.js)
  • Тесты: каждая нужда имеет 2-3 теста (detect satisfied/unsatisfied, правильный prefer_skill)

rc.3 — Event-driven awareness + skill pre-emption

Цель: bot reacts within ~100ms to env changes (fall, teleport, damage, hostile spawn near).

  • runtime/awareness/events.js — установка listeners:
    • bot.on('move') — детект position-jump >5 блоков за тик → событие forced-move → инвалидация current dispatch context
    • bot.on('health') — снижение HP > 2 за тик → reflex.preempt()
    • bot.on('entitySpawn') — враждебный <12 блоков → reflex.preempt()
    • bot.on('blockUpdate') около бота (manhattan <4) → пометка environment_changed=true
  • runtime/awareness/state.js — храним flags (forcedMove, lastDamage, hostileAdded, envChanged), expose consumeFlags() для reflex
  • Skill protocol extended: execute(ctx, args) теперь получает ctx.abortSignal (AbortSignal). Длинные операции (pathfinder.goto, collectBlock loops) проверяют signal.aborted между шагами и сразу возвращают {ok: false, code: 'preempted'}
  • runtime/reflex.js: при срабатывании preempt-флагов вызывается currentDispatch?.abort(), и reflex запускает следующий тик немедленно (не ждёт DISPATCH_INTERVAL_MS)
  • recovery.tunnel-out, survive.pillar-up, gather.logs, explore.far адаптируются под AbortSignal (минимальное — if (signal.aborted) return { ok:false, code:'preempted' } после каждого await)
  • Связка с fast advisor: когда preempt сработал из-за forcedMove или environment_changed, и reflex не находит очевидный skill, вызывает fastAdvisor.advise(...) чтобы получить тактический совет (rc.1 scaffolding активируется здесь)

Acceptance signals (после rc.3)

  • В живой БД: lessons WHERE applied_count > 0 растёт (сейчас 3, должно стать 20+ за сутки)
  • Bot движется к конкретным целям: видимый прогресс инвентаря (wood → pickaxe → stone → axe), а не "блуждание в одном квадранте"
  • При forcedMove бот меняет план в течение секунды, не продолжает старый skill
  • Fast advisor пакетно срабатывает <10 раз/час, каждый раз приводит к смене skill (логируется)

Что отложено в v0.3.1

  • Vision (multimodal LLM на скриншотах) — требует prismarine-viewer pipeline + multimodal model в провайдере; не в первом релизе
  • Vector memory of scenarios — embeddings от похожих ситуаций
  • Auto-curriculum from wiki — фоновый паук minecraft.wiki

Workflow notes

  • Каждый rc — отдельный PR, мержим после approve
  • main защищён, auto-patch открывает PR с тегом auto-patch
  • Если что-то ломается в проде (живой бот в петле >30 мин), откатываем на v0.2.0-rc.3 commit 865aae1 через git checkout <commit> на ветке revert/v0.3.0-stability
  • Тестовые данные строго в /tmp/pepa-test-state-* (исправлено в v0.2.0-rc.2)