feat(runtime): village progression — crafting, tech-tree, LLM planner #11

Merged
halofourteen merged 1 commits from feat/village-tech-tree-planner into main 2026-05-25 17:00:07 +03:00
halofourteen commented 2026-05-25 17:00:04 +03:00 (Migrated from github.com)

Scope

Closes "бот стоит, копит proposals" → "копит ресурсы, строит к глобальной цели" pivot.

Three pieces in one PR:

1. Crafting primitives (`runtime/actions.js`)

`craftPlanks`, `craftSticks`, `placeCraftingTable` (reuses existing table within 4 m), `craftWoodenAxe`, `craftWoodenPickaxe`, `craftWoodenSword`. All use `bot.recipesFor`+`bot.craft` with a 15 s timeout. Same `{ok, detail}` shape as the other actions.

Helpers `inv.{getItemCount, getAnyPlanksCount, getAnyLogCount}` exported for cheap inventory checks in reflexes.

2. Tech-tree reflex (`runtime/reflex.js`)

New `techTreeReflex` between sleep and autonomous. Pure script (no LLM), 5 s cooldown:

Step Condition Action
1 `logs ≥ 1 && planks < 4` craft planks
2 `planks ≥ 2 && sticks < 4` craft sticks
3 `planks ≥ 3 && sticks ≥ 2 && !hasAxe` wooden_axe (places table)
4 `hasAxe && !hasPickaxe` wooden_pickaxe
5 `hasAxe && hasPickaxe && !hasSword` wooden_sword

3. LLM planner (`runtime/planner.js`)

Background `setInterval` every 15 min (+30 s warm-up). Reads `goal.md` + `plan.md` + slim snapshot, prompts Pi to output a fresh `plan.md`. Stripped of code fences, capped at 16 KB, written verbatim. Pi is told the format (numbered milestones, ✓ for done) and the constraints (overworld only, no OP, reach of current capabilities).

The reflex layer doesn't auto-execute the plan text yet — the plan is the long-horizon shape future reflexes (build house, plant farm) will read.

Progression now looks like

```
chop log (autonomous) →
craft planks → craft sticks → wooden_axe (tech-tree) →
chop faster (autonomous, has axe) →
wooden_pickaxe + wooden_sword (tech-tree) →
mine stone … (next PR: stone tools, farm site, house frame)
```

Test plan

  • All three modules import cleanly (sanity check passed)
  • Live: bot collects 4 logs → auto-crafts planks → auto-crafts sticks → auto-crafts axe
  • Live: after 30 s, `state//plan.md` appears, content reflects current goal
  • Live: `state//plan.md` regenerates every 15 min

Next PR (queued)

  • Stone-tier progression: mine cobblestone with wooden pickaxe → stone tools
  • Site selection: pick a flat spot near water + trees per goal.md
  • Build primitives: place block grid (3×3 frame for first hut)
  • Persistent `locations.json` for named places

🤖 Generated with Claude Code

## Scope Closes "бот стоит, копит proposals" → "копит ресурсы, строит к глобальной цели" pivot. Three pieces in one PR: ### 1. Crafting primitives (\`runtime/actions.js\`) \`craftPlanks\`, \`craftSticks\`, \`placeCraftingTable\` (reuses existing table within 4 m), \`craftWoodenAxe\`, \`craftWoodenPickaxe\`, \`craftWoodenSword\`. All use \`bot.recipesFor\`+\`bot.craft\` with a 15 s timeout. Same \`{ok, detail}\` shape as the other actions. Helpers \`inv.{getItemCount, getAnyPlanksCount, getAnyLogCount}\` exported for cheap inventory checks in reflexes. ### 2. Tech-tree reflex (\`runtime/reflex.js\`) New \`techTreeReflex\` between sleep and autonomous. Pure script (no LLM), 5 s cooldown: | Step | Condition | Action | |---|---|---| | 1 | \`logs ≥ 1 && planks < 4\` | craft planks | | 2 | \`planks ≥ 2 && sticks < 4\` | craft sticks | | 3 | \`planks ≥ 3 && sticks ≥ 2 && !hasAxe\` | wooden_axe (places table) | | 4 | \`hasAxe && !hasPickaxe\` | wooden_pickaxe | | 5 | \`hasAxe && hasPickaxe && !hasSword\` | wooden_sword | ### 3. LLM planner (\`runtime/planner.js\`) Background \`setInterval\` every 15 min (+30 s warm-up). Reads \`goal.md\` + \`plan.md\` + slim snapshot, prompts Pi to output a fresh \`plan.md\`. Stripped of code fences, capped at 16 KB, written verbatim. Pi is told the format (numbered milestones, ✓ for done) and the constraints (overworld only, no OP, reach of current capabilities). The reflex layer doesn't auto-execute the plan text yet — the plan is the long-horizon shape future reflexes (build house, plant farm) will read. ## Progression now looks like \`\`\` chop log (autonomous) → craft planks → craft sticks → wooden_axe (tech-tree) → chop faster (autonomous, has axe) → wooden_pickaxe + wooden_sword (tech-tree) → mine stone … (next PR: stone tools, farm site, house frame) \`\`\` ## Test plan - [x] All three modules import cleanly (sanity check passed) - [ ] Live: bot collects 4 logs → auto-crafts planks → auto-crafts sticks → auto-crafts axe - [ ] Live: after 30 s, \`state/<host>/plan.md\` appears, content reflects current goal - [ ] Live: \`state/<host>/plan.md\` regenerates every 15 min ## Next PR (queued) - Stone-tier progression: mine cobblestone with wooden pickaxe → stone tools - Site selection: pick a flat spot near water + trees per goal.md - Build primitives: place block grid (3×3 frame for first hut) - Persistent \`locations.json\` for named places 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.