fix(v0.3.1): storyline beats manifesto L1+ (only L0 alive emergencies override)

Found in live logs after the previous commit deployed:
  storyline: step 1/11: orient_self → explore.wander
  advisor-trigger: firing because wedged (planned=survive.acquire-food, ...)

Manifesto was still picking survive.acquire-food (L1 food) over the
storyline's orient_self → explore.wander. That's the wrong precedence —
storyline expresses a *concrete operational subgoal* and L1+ manifesto
needs are just "you'd benefit from food" priorities, not emergencies.

New dispatch precedence in curriculumReflex:
  1. manifesto L0 (alive emergencies: lava, low-HP+hostile, food=0)
  2. storyline (concrete narrative subgoal — beats L1+ manifesto)
  3. manifesto L1+ (fallback when storyline has no concrete suggestion)
  4. curriculum plan (legacy fallback)

This way the bot starts following the narrative arc even while
manifesto's L1 food is technically unsatisfied — orient_self runs to
completion before pursuing food explicitly. Storyline already handles
food as step 5 (first_food), so we're not skipping it.

Tests: 378 green (+2 priority-ordering tests):
- L0 manifesto emergency: upstream reflex (defend/modes) catches before
  curriculum dispatch
- storyline beats manifesto when both have suggestions: well-fed bot
  with logs → craft.planks (storyline crafting_basics), not gather.logs
  (manifesto L2)
- updated "manifesto fallback" test to require disableStoryline=true

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 20:39:25 +03:00
co-authored by Claude Opus 4.7
parent 7f545723b5
commit 21462dfdb1
2 changed files with 81 additions and 11 deletions
+23 -10
View File
@@ -540,16 +540,29 @@ function curriculumReflex(ctx) {
return { action: "dispatched", kind: "curriculum-wander", label: "wander" };
}
// Pick what to dispatch. Order: manifesto > storyline > curriculum.
// Manifesto is highest because L0 alive emergencies (lava, low-HP +
// hostile) must override any narrative aspiration. Storyline beats
// curriculum because it expresses a concrete operational subgoal,
// not just "next milestone".
let skillId = manifestoSkillId ?? storySkillId ?? plan.skillId;
let skillSource = manifestoSkillId
? `manifesto:${activeNeed.need.id}`
: storySkillId ? `storyline:${storyStep.step.id}`
: "curriculum";
// Pick what to dispatch. Order:
// 1. manifesto L0 (alive emergencies: low HP near hostile, lava
// under foot, food=0) — absolute priority; do NOT let
// storyline overrule a "you're dying" signal.
// 2. storyline — concrete narrative subgoal ("collect 8 logs",
// "craft wooden pickaxe"). Beats manifesto L1+ because the
// ladder needs operational direction, not just "you need food
// → dispatch acquire-food forever".
// 3. manifesto L1+ — fallback when storyline has no concrete
// pursue (e.g. armor levels with pursue=null).
// 4. curriculum plan — legacy fallback.
const manifestoEmergency = activeNeed?.need?.level === 0;
let skillId, skillSource;
if (manifestoEmergency) {
skillId = manifestoSkillId ?? storySkillId ?? plan.skillId;
skillSource = `manifesto:${activeNeed.need.id}`;
} else if (storySkillId) {
skillId = storySkillId;
skillSource = `storyline:${storyStep.step.id}`;
} else {
skillId = manifestoSkillId ?? plan.skillId;
skillSource = manifestoSkillId ? `manifesto:${activeNeed.need.id}` : "curriculum";
}
// v0.3.0 fast-advisor: if a fresh recommendation is sitting on ctx
// (the result of a previous tick's async advise() call), use it.