Přeskočit na obsah

Kořen, který nebyl základ — nastavení platné pro jediný profil

Hermes · konfigurace profilů
Strop v configu
3 200 znaků
Strop, který platil
1 375
Přetečená úložiště
3 ze 4
Chybových hlášek
0

Stalo se 8. 9. 2026 při rutinní kontrole po aktualizaci runtime. Zeptal jsem se obchodního profilu na kontrolní dotaz se známou odpovědí a on místo odpovědi čtyřikrát po sobě sáhl do vlastní paměti:

Memory at 1,369/1,375 chars. Adding this entry would exceed the limit.
Refusing to empty MEMORY.md: this batch would remove every entry

Nejdřív zkusil přidat záznam, pak sloučit, pak vyprázdnit celé úložiště — a teprve když ho pojistka zastavila, dostal se k práci. Stálo to čtyři volání modelu za jediný tah.

Divné na tom bylo číslo 1 375. V konfiguraci mám ten strop nastavený na 3 200, a to od začátku srpna. Nastavení bylo vidět, bylo správně napsané a neplatilo.

Kořen není báze

co jsem předpokládal~/.hermes/config.yamluser_char_limit: 3200dědí seprofil zdravístrop 3 200jak to doopravdy je~/.hermes/config.yaml= config výchozího profiluמádná dědičnostprofil zdravívlastní HERMES_HOMEklíč chybívestavěné defaultystrop 1 375Kořen sousedí s adresářem profilů, a proto vypadá nadřazeně. Je to jen jeden z nich, náhodou o patro výš.

Cesta ke konfiguračnímu souboru se odvozuje z domovského adresáře runtime. A profil si ten domovský adresář přesměruje k sobě — má vlastní přihlašovací údaje, vlastní logy, vlastní databázi. Soubor v kořeni tedy není sdílená báze, ze které profily čerpají. Je to konfigurace jednoho konkrétního profilu, toho výchozího.

Co v profilu napsané není, nespadne na kořen. Spadne na vestavěné hodnoty zadrátované v kódu. A ta vestavěná hodnota je právě 1 375 — s komentářem „~500 tokenů", tedy střízlivý default pro někoho, kdo si nic nenastavil.

Kontrola, kterou to bylo vidět, trvala minutu: přečíst si hodnotu tak, jak ji vidí profil, ne tak, jak ji vidím já.

profil uloženo strop, který platil
výchozí 3 194 3 200 na hraně
zdraví 3 050 1 375 222 %
obchodování 1 369 1 375 plné
kódování 490 1 375 v pořádku

Tři ze čtyř úložišť přes strop nebo na něm. Zápis do nich selhával a časová razítka souborů říkají, jak dlouho: zdravotní profil se naposledy povedlo zapsat 18. srpna, tedy tři týdny předtím, než mě na to náhoda upozornila u úplně jiného profilu.

Proč nic neupozornilo

Strop se kontroluje jen v operaci přidat. Není to periodická kontrola, není to nic, co by se ozvalo při startu, a diagnostický příkaz runtime na to nemá test. Přetečené úložiště se tedy neprojeví jako chyba, ale jako agent, který se občas chová divně a spálí pár tahů navíc — což je přesně ten druh příznaku, který si vysvětlíš jinak a jdeš dál.

Zajímavější je, že to samé se stalo v srpnu na jiném klíči. Blok s nastavením pomocných úloh (komprese kontextu, hledání v sezeních) je taky jen v kořeni. Profily bez vlastního bloku zůstaly v automatickém režimu, ten po vyčerpání kvóty cloudového modelu sáhl na lokální model — a lokální model neměl na velký kontext, takže vracel chybu ve smyčce. Stálo to 26 minut procesorového času a zatuhlý profil, než jsem přišel na to, že se to vůbec děje.

Dva nezávislé nálezy na dvou různých klíčích. To už není historka, to je vlastnost.

Co jsem přitom udělal špatně

Testoval jsem to nástrojem se stejnou vadou. Napsal jsem si skript, který načte konfiguraci, a pustil ho třikrát s různým jménem profilu v proměnné prostředí. Dostal jsem třikrát identický výstup — a chvíli to bral jako důkaz, že je všude všechno stejně nastavené. Podezřele identický by mě měl trknout dřív: profily mají různé modely, různé nástroje, různé limity tahů. Ve skutečnosti jsem třikrát přečetl tentýž kořenový soubor, protože rozhoduje domovský adresář, ne jméno profilu. Ověřovací nástroj opakoval přesně tu chybu, kterou jsem hledal.

A druhá věc, mimo tenhle nález, ale ze stejného dne. Diagnostika hlásila zranitelnosti v npm závislostech a nabízela příkaz na opravu. Pustil jsem obecnou variantu místo té, kterou nástroj používá sám. Obecná varianta rozbalila i část stromu určenou pro desktopovou aplikaci a stáhla 400 MB závislostí na stroj, kterému dva dny předtím došlo místo na disku a tvrdě kvůli tomu zastavil. Důvod toho omezení byl přitom napsaný v dokumentačním komentáři té funkce, dva řádky nad příkazem, který jsem nepoužil.

Obojí je táž chyba jako minule: věřit tvrzení, které vzniklo jinou cestou než ta, o kterou mi jde. V nálezu 30 to byl diagnostický příkaz, který otevřel spojení na server, zatímco agent bral nástroje odjinud. Tady je to skript, který čte kořen, zatímco profil čte sebe.

Strop není alokace

Půl hodiny jsem přemýšlel, co z paměti vyškrtat, aby se to vešlo. Zbytečně. Do promptu jde skutečný obsah souboru, ne kapacita — zvednout strop nestojí nic a nezvětší to jediný tah. Strop je pojistka proti nekontrolovanému růstu, ne rozpočet, který se předem odečítá.

Škrtat se přesto vyplatilo, ale z jiného důvodu. Ty čtyři záznamy v obchodním profilu říkaly totéž — preference formátu briefingu, dvakrát anglicky, jednou česky, počtvrté zase anglicky. A všechny ty údaje už stály v instrukčním souboru toho profilu, který píšu ručně. Agent si tedy do paměti ukládal parafráze vlastního zadání a platil za ně místem v promptu při každém tahu. Po sloučení do jednoho záznamu zbylo z 1 369 znaků 604 a neztratil se ani jeden fakt.

Co se pro to změnilo
  • configkaždý profil dostal vlastní blok `memory:`; hodnota v kořeni platí jen pro jeden z nich
  • postupnastavení se ověřuje očima profilu (přes jeho `HERMES_HOME`), ne skriptem, který si profil jen řekne jménem
Souvisí — štítek „provoz“