- README: update lede, architecture block, self-improvement section, status.
Mentions knowledge.db, coach/advice loop, persona narration, and the new
PR-based auto-patch flow.
- scripts/auto-patch.js: replace cherry-pick-to-main with `git push` +
`gh pr create`. The operator is now the only one who can merge into main
(enforced by branch protection rules on the remote). Legacy direct-merge
path remains behind PEPA_AUTO_PATCH_MERGE=cherry-pick for emergencies.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Five concrete patterns from Voyager and Mindcraft, applied in our shape
without abandoning the git-as-evolution-substrate that makes pepa
distinct. Plus a first multi-agent surface so two bots from the same
repo can share intent.
1. runtime/critic.js (Voyager critic.txt)
- Spawns `pi -p` with a JSON-only critic prompt before a proposal is
written. {reasoning, success, critique}.
- success=true short-circuits the proposal (bot recovered between
detector tripping and now), saving Pi tokens on false positives.
- critique is spliced into the proposal body via attachCritique() so
the downstream auto-patcher has a sharp spec.
- Graceful: pi missing / timeout / unparseable JSON → proposal still
filed without the critic block.
2. scripts/lint-patch.js (Mindcraft coder._lintCode)
- Pre-flight gate between Pi commit and npm test: node --check, dynamic
import (catches missing named exports), regex extraction of
runSkill("id") calls cross-checked against the live registry.
- Cheaper than npm test, fails fast with a clear reason.
3. runtime/stuck-incident.renderActionTemplate (Voyager action_template.txt)
- All proposal bodies now follow the same fixed-section layout: Task /
Last result / Execution error / State / Metrics / Journal /
Scenarios / Critique / Fix / Edit scope / Forbidden.
4. runtime/skill-library.js (Mindcraft skill_library.getRelevantSkillDocs)
- Word-overlap ranking (Mindcraft's offline fallback) — zero deps,
deterministic. auto-patch.js injects top-3 similar skills into the
Pi prompt as "look at these patterns".
5. runtime/modes.js (Mindcraft modes.js)
- Declarative {name, interrupts, on, active, update(ctx)} chain that
runs BEFORE the curriculum each tick.
- Ships self_preservation (low HP → eat/flee), hunger (food<14 → eat),
night_shelter (night + bed in hand → sleep). Cleaner than ad-hoc
lastFleeAttempt cooldowns in reflex.js.
6. runtime/social/conversation.js + cmd:conv-say/conv-recent/conv-list
- File-JSONL topic channel so two bots from the same repo (different
usernames, different host dirs under state/) can append turns and
read peers. Skeleton — multi-agent collaboration on top later.
Differentiator preserved: every Pi-written skill still lands on main via
auto-patch.js (real git branch + smoke gate + cherry-pick). Voyager
keeps skills in a Chroma JSON, Mindcraft keeps them in RAM — pepa keeps
them as versioned source code reviewable in `git log`.
package.json: 0.0.1 → 0.1.0. 174/174 tests pass. README + AGENTS updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When Pi writes a multi-file runtime patch, the supervisor's file watcher
can fire between two consecutive writes, kill the bot mid-edit, and load
a half-saved file with a SyntaxError. Loop until the operator stops it.
scripts/auto-patch.js now creates state/auto-patch.lock with its PID
right after the branch checkout (before spawning pi -p), and removes
it on every exit path. runtime/supervisor.js defers any watch-triggered
restart while the lock holder is alive, polling every 2 s; once the
lock drops it waits 1.5 s for the final write to settle, then runs
\`node --check\` on the changed file and only restarts if it parses.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two safety rails on the unattended self-improvement loop:
1. scripts/edit-scope.js + .test.js: pure helpers that parse
`editScope: [...]` out of a proposal frontmatter (the field Phase 6
started writing) and validate a list of changed files against it.
13 tests covering null/missing/malformed frontmatter, directory
prefix matching, exact-file matching, default-scope fallback.
2. scripts/auto-patch.js:
- reads editScope from the proposal (falls back to ["runtime/"])
- injects the allowed paths into the Pi prompt so Pi knows the
boundaries up front
- validates the diff against scope + auto-allows any
runtime/**/*.test.js files Pi added
- runs `npm test` on the patched branch BEFORE cherry-picking;
refuses to land a patch that breaks the suite
Closes the "Smoke checks run before applying patch" item from
plans/autonomous-survival-bot-prd.md §7 Phase 6. npm test now 92/92.
Co-authored-by: Yuriy Mayatnikov <mayatnikov@me.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>