mandrock-files / ai

shove-replay

Реконструкція сесії AI-агента з журналу команд, коли вихідний код версії інструменту, яким агент користувався, уже втрачено — на прикладі гри SHOVE.

shove-replay: реплей сесії агента, коли рушій уже не той

SHOVE — тактична головоломка в дусі Into the Breach: загін мехів тримає три будівлі проти багів, п'ять ходів на все. Кожен ворог наперед світить офсет свого удару — цей офсет і зветься телеграфом. Штовхнути атакера — це перенаправити його в воду до сусіда, а не бити в лоб.

Спроєктувала, закодила і зіграла гру Claude Fable 5 — без людини за штурвалом, шість партій поспіль. Репо: robss2020/claude-fable-5-having-fun.

Але цікаве тут не гра. Цікаве — те, що від неї лишилось на диску.


Що насправді зберігається в журналі

Play ledger — журнал зіграних партій — тримає тільки команди, стану дошки в ньому нема. Щоб побачити партію знову, береш той самий сід і ганяєш той самий рушій з нуля, крок за кроком. Це детерміноване відтворення, а не запис відео: рушій — джерело істини, лог — просто вхід для нього (відео показало б картинку саме по собі; лог без рушія не показує нічого).

Наслідок прямий, як обрив кабелю: без точної версії рушія лог — просто список чисел.


Проблема: рушій перерів сам себе

За шість партій рушій переписав сам себе шість разів (v1–v6). Вихідний код v1–v5 уже втрачено — ніхто, включно з агентом, який його й писав, не здогадався заархівувати рушій окремо від логів, що він плодив. Реально відтворюваною лишилась одна партія з шести: S6, сід 31337, на v6. П'ять інших живуть як список команд, який більше нема чим програти.


Рішення: чесна межа замість імітації

Viewer, який я зробив під це, реконструює єдину уцілілу партію: грид-борд, юніти, вороги і — головне — locked-in телеграф кожного ворога в кожен момент. Тобто рівно та позиція, яку рушій бачив, коли приймав рішення. Апстрім (shove.py) ліцензії не має, тому я його не вендорю — він тягнеться at build time; MIT у репо покриває лише сам viewer, чужий код лишається чужим.

Для п'яти втрачених сесій я не став нічого домальовувати. Синтетичний стан, підставлений замість втраченого, — та сама дистиляція, тільки в пікселях: виглядає повно, а насправді брехня. Чесніше показати межу відтворюваного, ніж видати реконструкцію за факт.

Демо: tools.mandrock.me/shove-replay · Репо viewer'а: github.com/0mandrock1/shove-replay


Таблиця рішень

Ситуація Що робити
Є журнал команд, стану немає реконструювати детерміновано реплею; потрібен точний рушій і точний сід
Версія рушія, яка грала сесію, невідома або загублена сесія непридатна до реплею; визнати це, не імітувати стан
Апстрім без ліцензії, потрібен для роботи не вендорити чужий код; тягнути at build time, ліцензувати окремо лише свій шар
Інструмент агента змінюється між сесіями версіонувати й архівувати рушій окремо від логів, які він генерує
Треба показати, що саме бачив агент у момент рішення зберігати сирі проміжні сигнали (офсет/намір), не лише кінцевий стан

Антипатерни


Чекліст

P.S. — рушій штовхнув сам себе
      SHOVE: РУШІЙ ШТОВХАЄ САМ СЕБЕ

     ┌─────────────────────────────────┐
     │ хід: SHOVE(власний вихідний код)│
     └─────────────────────────────────┘
                       │
              ┌─────────┴────────────────┐
              ▼                          ▼
┌──────────────────────┐   ┌──────────────────────┐
│ куди полетів удар    │   │ що встигли прочитати │
│ (v1–v5)              │   │ (v6, seed 31337)     │
└──────────────────────┘   └──────────────────────┘
              ▼                          ▼
┌──────────────────────┐   ┌──────────────────────┐
│ 0 байт коду,         │   │ 1 партія з 6,        │
│ назавжди             │   │ єдина яку видно      │
└──────────────────────┘   └──────────────────────┘

Телеграф показує, куди прилетить удар. На свій власний рушій так жодного разу й не глянув.