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>
4.0 KiB
4.0 KiB
pepa v0.3.0 — status
Live tracking document for the v0.3.0 iteration ("Maslow + Awareness").
See PLAN.md for the full design.
Shipped
rc.1 — Live skill registry + Fast advisor scaffold
Root problem solved: 47/47 Pi-extracted lessons in v0.2.x had
applied_count = 0 because Pi was hallucinating skill ids
(relocate.surface, choose.safe.surface, survive.shelter,
gather.visible_log, …) that don't exist in the registry. Both halves
fixed: (a) Pi now sees the real registry in its system prompt,
(b) anything that still slips through gets rejected at consult time.
runtime/skill-registry.js— single source of truth wrappingskills/index.js. Exports:listSkillIds()— live id listisRegistered(id)— bool checkdescribeSkill(id)— id/title/timeoutMsskillRegistryPrompt({ limit })— prompt-ready block grouped by namespace, with "USE ONLY THESE, never invent" instruction
runtime/llm/provider.js— OpenAI-compatible chat client, env-driven:PEPA_FAST_LLM_BASE_URL(defaulthttps://api.openai.com/v1)PEPA_FAST_LLM_API_KEY(required to enable; safe no-op otherwise)PEPA_FAST_LLM_MODEL(required)PEPA_FAST_LLM_TIMEOUT_MS(default 8000)- Supports JSON-mode via
response_format: { type: "json_object" } - Surfaces
not_configured,no_model,http_<status>,network_error,timeout,bad_jsoncodes
runtime/coach/fast-advisor.js— tactical "what now?" tier. Scaffold only in rc.1; auto-trigger comes in rc.3.advise({snapshot, reason, recentSkillIds, lessonsTail})→{action: 'switch_skill'|'continue'|'wait', skillId?, rationale}- Rejects any returned
skill_idnot in the live registry - Rate-limit: 6 calls/hour, 30s cooldown between calls
- System prompt embeds registry; user prompt carries snapshot + trigger
runtime/coach/advice.js:normalisePreferSkill()now returnsnullfor anything not in registry/mode-map (was: passed through unchanged → dispatcher crashed atrunSkill())- Logs
warnline when a hallucinated prefer_skill is dropped
runtime/coach/postmortem.js:- Pi prompt includes the live registry block (
skillRegistryPrompt) with a "CRITICAL: USE ONLY THESE" instruction - On insert, drops
prefer_skill/avoid_skillthat's neither a registered id nor a known mode name; warn-logs the count
- Pi prompt includes the live registry block (
runtime/coach/reflect.js— same treatment as postmortem (registry in prompt + write-time filter)
Tests: 279 green (was 257 on rc.3). Added:
runtime/skill-registry.test.js— 5 testsruntime/llm/provider.test.js— 9 testsruntime/coach/fast-advisor.test.js— 10 tests
rc.2 — (pending) Manifesto / Needs ladder
rc.3 — (pending) Event-driven awareness + skill pre-emption
Next session quick start
- Read PLAN.md for the full design and per-rc breakdown.
- Check live DB to see if Pi-lesson application is improving:
After rc.1 deploys, expect Pi-coach/Pi-reflect
sqlite3 state/play.xmatic.team_25565/knowledge.db \ "SELECT source, COUNT(*) AS n, SUM(applied_count > 0) AS applied FROM lessons GROUP BY source ORDER BY n DESC;"appliedcount to start growing as the registry feedback closes the loop. - Set fast-advisor env when ready to test:
The advisor still isn't auto-triggered in rc.1 — it's wired in rc.3.
export PEPA_FAST_LLM_BASE_URL="https://<timeweb-endpoint>/v1" export PEPA_FAST_LLM_API_KEY="<key>" export PEPA_FAST_LLM_MODEL="gpt-5-mini" - Pick the next rc from PLAN.md.
Workflow notes
- main is protected — only operator merges PRs
- Tests:
npm test(279 green at last check), isolated under/tmp/ - The bot supervisor hot-restarts on file changes in
runtime/**/*.js - If something regresses badly, revert to v0.2.0-rc.3 commit
865aae1