chore: snapshot pre-v0.2.0 WIP (pathfinder/reflex/metrics/skills improvements)

Baseline for the v0.2.0 self-learning iteration. All 205 tests pass on this
state. Subsequent commits in this branch layer the knowledge base,
post-mortem coach, and persona narration on top.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 13:05:12 +03:00
co-authored by Claude Opus 4.7
parent 3ee2ab886e
commit 86e5294bb8
30 changed files with 1023 additions and 130 deletions
+87
View File
@@ -45,6 +45,7 @@ function makeCtx({
lastEatAt = 0,
lastSleepAttemptAt = 0,
lastCurriculumAt = 0,
metrics,
} = {}) {
const dispatches = [];
const ctx = {
@@ -56,6 +57,7 @@ function makeCtx({
lastSleepAttemptAt,
lastCurriculumAt,
skillBackoff,
metrics,
dispatch(fn, label, opts = {}) {
dispatches.push({ fn, label, opts });
},
@@ -82,6 +84,23 @@ test("disconnected snapshot → no dispatch", () => {
assert.equal(dispatches.length, 0);
});
test("mode hit dispatches the returned skill immediately", () => {
const { ctx, dispatches } = makeCtx({
snapshot: {
connected: true,
health: 4,
food: 10,
hasFood: true,
inventory: { bread: 1 },
curriculum: { plan: { skillId: "gather.logs" } },
},
});
const out = runTick(ctx);
assert.equal(out.reflex, "mode:self_preservation");
assert.equal(out.action, "dispatched");
assert.equal(dispatches[0].label, "survive.eat");
});
test("defend wins over curriculum when hostile in melee", () => {
const { ctx, dispatches } = makeCtx({
snapshot: {
@@ -279,6 +298,74 @@ test("wander-hint backoff swaps skill for wander on the next tick", () => {
assert.equal(dispatches[0].label, "wander");
});
test("recent repeated skill timeouts trigger metric recovery", () => {
const now = Date.now();
const { ctx, dispatches } = makeCtx({
snapshot: {
connected: true,
health: 20,
food: 20,
isDay: true,
curriculum: { plan: { skillId: "gather.logs" } },
},
metrics: {
snapshot: () => ({
"gather.logs": { ok: 0, fail: 3, lastTs: now, lastCode: "timeout" },
}),
},
});
const out = runTick(ctx);
assert.equal(out.reflex, "curriculum");
assert.equal(out.kind, "curriculum-metric-recovery");
assert.equal(dispatches[0].label, "explore.far");
assert.ok((ctx.skillBackoff?.["gather.logs"] ?? 0) > Date.now());
});
test("recent movement timeouts trigger tunnel recovery", () => {
const now = Date.now();
const { ctx, dispatches } = makeCtx({
snapshot: {
connected: true,
health: 20,
food: 20,
isDay: true,
curriculum: { plan: { skillId: "gather.logs" } },
},
metrics: {
snapshot: () => ({
"explore.far": { ok: 0, fail: 1, lastTs: now, lastCode: "timeout" },
}),
},
});
const out = runTick(ctx);
assert.equal(out.reflex, "curriculum");
assert.equal(out.kind, "curriculum-metric-recovery");
assert.equal(dispatches[0].label, "recovery.tunnel-out");
});
test("successful tunnel recovery clears movement-timeout trigger", () => {
const now = Date.now();
const { ctx, dispatches } = makeCtx({
snapshot: {
connected: true,
health: 20,
food: 20,
isDay: true,
curriculum: { plan: { skillId: "gather.logs" } },
},
metrics: {
snapshot: () => ({
"explore.far": { ok: 0, fail: 1, lastTs: now - 5_000, lastCode: "timeout" },
"recovery.tunnel-out": { ok: 1, fail: 0, lastTs: now, lastCode: "done" },
}),
},
});
const out = runTick(ctx);
assert.equal(out.reflex, "curriculum");
assert.equal(out.kind, "curriculum-skill");
assert.equal(dispatches[0].label, "gather.logs");
});
test("onComplete sets wander hint when skill recovery says so", () => {
const { ctx, dispatches } = makeCtx({
snapshot: {