CCCPaste

1ef41a46e5f80

Masz rację: nie powinniśmy próbować utrzymywać jednej fizycznej sesji bez końca. Powinniśmy utrzymywać jeden logiczny projekt, który może przechodzić przez wiele mniejszych sesji i zadań.

Mój konkretny wybór rozwiązania:

- trwały „Project Ledger” w określonym katalogu,
- automatyczny zapis po każdym turnie,
- osobne segmenty dla zadań,
- kontrolowany checkpoint przed kompresją,
- wstrzyknięcie małej kapsuły stanu przed kolejnym zapytaniem,
- fail-closed: bez poprawnie zapisanego checkpointu nie wolno kompaktować,
- proaktywne przechodzenie do świeżej sesji przy granicy zadania zamiast czekania na awarię kontekstu.

Plan zapisałem tutaj:

/home/hermit/plans/2026-09-01-hermes-project-ledger/IMPLEMENTATION_PLAN.md

Dodatkowe ustalenia techniczne:

/home/hermit/plans/2026-09-01-hermes-project-ledger/thinking.md

1. Czy Hermes już ma miejsca do wstrzyknięcia?

Tak. W obecnej wersji są cztery przydatne punkty.

Po każdym zakończonym turnie:

python
sync_turn(...)


Możemy wtedy automatycznie zapisać:

- wiadomość użytkownika,
- odpowiedź agenta,
- użyte narzędzia,
- zmienione pliki,
- dokładne błędy,
- wyniki testów,
- nowe zadania wykryte podczas pracy.

Przed następnym wywołaniem modelu:

python
prefetch(query)


Możemy wstrzyknąć małą kapsułę aktywnego zadania. Nie do system promptu, tylko do kontekstu bieżącego requestu, żeby nie niszczyć cache.

Przed kompresją:

python
on_pre_compress(messages)


Możemy:

- zapisać pełny checkpoint,
- zaktualizować dokumentację projektu,
- zwrócić kompaktorowi ustrukturyzowany handoff,
- przekazać ścieżkę i hash checkpointu.

Po kompresji:

python
on_session_switch(..., reason="compression")


Ten hook w Twojej wersji działa zarówno przy kompresji in-place, jak i przy zmianie identyfikatora sesji. Możemy wtedy:

- potwierdzić, że checkpoint odpowiada wykonanej kompresji,
- wyczyścić przetworzone bufory,
- oznaczyć checkpoint jako użyty,
- przygotować jednorazową kapsułę dla pierwszego turnu po kompresji.

Czyli technicznie dokładnie to, o czym mówisz, jest możliwe.

2. Gdzie przechowujemy dokumentację?

Proponuję jedno jawnie skonfigurowane miejsce:

yaml
project_ledger:
root: /home/hermit/plans/agent-projects


Przykładowa struktura:

text
/home/hermit/plans/agent-projects/<project-id>/
├── PROJECT.md
├── INDEX.md
├── DECISIONS.md
├── BLOCKERS.md
├── ARTIFACTS.md
├── manifest.json
├── journal/
│ └── events.jsonl
└── tasks/
├── T-0001-authentication/
│ ├── TASK.md
│ ├── STATE.md
│ ├── TODO.md
│ ├── SOURCES.md
│ └── checkpoints/
│ ├── C-000001.md
│ └── C-000002.md
└── T-0002-browser-qa/
└── ...


Znaczenie:

- PROJECT.md — cel, zakres, ograniczenia i kryteria zakończenia projektu,
- INDEX.md — krótki indeks zadań i zależności,
- DECISIONS.md — decyzje wraz z uzasadnieniem,
- BLOCKERS.md — aktualne i rozwiązane blokery,
- ARTIFACTS.md — ścieżki, branche, testy i runtime,
- journal/events.jsonl — append-only źródło odzyskiwania,
- tasks/T-... — osobne segmenty tematyczne,
- checkpoints/ — niezmienne snapshoty przed kompresją.

Ważne: nie tworzymy jednego ogromnego pliku dokumentacji. To ponownie zrobiłoby z dokumentacji wielki kontekst. INDEX.md służy tylko jako mapa, a szczegóły są dzielone na zadania.

3. Jak agent rozbija projekt?

Hierarchia:

text
Projekt → obszar prac → zadanie → podzadanie → checkpoint


Statusy:

text
discovered → planned → active → blocked → done


Nowe zadanie powstaje, gdy:

- ma osobne kryteria akceptacji,
- dotyczy innego subsystemu,
- można je niezależnie przetestować,
- może zostać niezależnie zablokowane,
- może być wykonane/delegowane niezależnie,
- aktualne STATE.md robi się za duże,
- poprzednie zadanie zostało zakończone.

Nie rozbijamy projektu per wywołanie narzędzia. Sensowny segment to około 30–90 minut spójnej pracy albo jeden niezależnie weryfikowalny rezultat.

Każde zadanie musi mieć:

- cel,
- zakres i non-goals,
- kryteria akceptacji,
- zależności,
- aktualny stan,
- zakończone działania z dowodami,
- blokery,
- dokładnie jeden następny krok.

Nowe tematy wykryte przez agenta dostają status discovered. Nie mogą samodzielnie wyprzeć aktywnego celu użytkownika.

4. Co dzieje się po każdym turnie?

Automatycznie, niezależnie od tego, czy model pamięta o dokumentacji:

1. Hermes zapisuje zdarzenie do journal/events.jsonl.
2. Zdarzenie otrzymuje stabilny identyfikator i hash.
3. Zapisywane są dokładne:
- ścieżki,
- błędy,
- wyniki testów,
- decyzje,
- identyfikatory tasków.
4. Jeżeli pojawił się nowy temat, zostaje dodany do TODO jako discovered.
5. Co określoną liczbę turnów model dokumentacyjny aktualizuje pliki Markdown.

Dzięki temu nawet jeśli model dokumentacyjny padnie, mamy surowy journal, z którego można odbudować dokumentację.

5. Co dokładnie dzieje się przed kompresją?

To będzie transakcja:

1. Blokada dla (project_id, session_id).
2. Flush wszystkich zdarzeń do journala.
3. Model checkpointujący generuje ustrukturyzowany wynik:
- zmiany tasków,
- wykonane działania,
- decyzje,
- blokery,
- pliki,
- testy,
- następny krok,
- krótką kapsułę handoff.
4. Kod waliduje wynik.
5. Dokumenty są zapisywane do plików tymczasowych.
6. Następuje fsync i atomowy rename.
7. manifest.json jest aktualizowany jako ostatni.
8. Obliczany jest hash checkpointu.
9. Dopiero wtedy kompaktor może zastąpić starszy kontekst.
10. Kompaktor dostaje kapsułę oraz wskaźnik:

text
Checkpoint: C-000123
Task: T-0007
Path: .../tasks/T-0007/checkpoints/C-000123.md
Digest: sha256:...
Next action: ...


Jeżeli dokumentacja nie została poprawnie zapisana, kompresja nie może się odbyć.

6. Najważniejsza luka w obecnym Hermesie

Twoja lokalna wersja wywołuje on_pre_compress(), ale przechwytuje i ignoruje jego wyjątki:

python
try:
memory_context = memory_manager.on_pre_compress(messages)
except Exception:
pass


Czyli provider może powiedzieć „nie udało się zapisać checkpointu”, a Hermes mimo to może kontynuować.

Aktualna dokumentacja upstream opisuje już lepszy kontrakt:

yaml
memory:
checkpoint_required: true


Wtedy brak checkpointu powinien kończyć się:

text
BLOCKED_MISSING_PREREQUISITE


i pozostawiać oryginalne wiadomości bez zmian.

Tego kontraktu nie ma jeszcze w Twojej zainstalowanej wersji. Pierwsza zmiana implementacyjna musi więc backportować właśnie ten mechanizm. Bez tego Project Ledger byłby wygodną
dokumentacją, ale nie gwarancją bezpieczeństwa.

7. Co wstrzykujemy do modelu?

Nie wszystkie dokumenty. Tylko kapsułę około 2–3,5 tysiąca tokenów:

text
[PROJECT LEDGER CAPSULE]
Project: impress-connect
Active task: T-0007

Objective:
...

Acceptance criteria:
...

Verified state:
...

Completed:
...

Blockers:
...

Next action:
...

Relevant documents:
- tasks/T-0007/STATE.md
- tasks/T-0007/SOURCES.md
- DECISIONS.md#D-0012

Latest checkpoint:
C-000123, sha256:...

Recovery:
Use ledger_get or session_search. Do not infer omitted details.
[/PROJECT LEDGER CAPSULE]


Dobór:

1. aktywne zadanie,
2. zadania wskazane bezpośrednio przez ID lub ścieżkę,
3. maksymalnie dwa powiązane zadania/zależności,
4. tylko istotne decyzje i ograniczenia projektowe.

Nie wstrzykujemy całego projektu przy każdym wywołaniu.

8. Czy model kompaktujący może sam tworzyć dokumentację?

Tak, ale nie powinien samodzielnie wykonywać niekontrolowanych zapisów.

Bezpieczny podział:

- model generuje ustrukturyzowane zmiany,
- kod waliduje wynik,
- kod zapisuje pliki atomowo,
- kod oblicza hash,
- dopiero potem Hermes zezwala na kompresję.

Model może więc przygotowywać dokumentację, ale nie jest autorytetem transakcji.

W pierwszej wersji proponuję dwa logiczne kroki:

1. checkpoint dokumentacyjny,
2. właściwa kompresja z wykorzystaniem checkpointu.

To jest trochę wolniejsze, ale użytkownik wyraźnie woli poświęcić więcej czasu i nie stracić pracy. Później można zoptymalizować to do jednego wywołania zwracającego:

json
{
"ledger_updates": [],
"handoff_summary": "...",
"active_task": "T-0007",
"next_action": "...",
"source_digest": "..."
}


9. Jak utrzymujemy „długą sesję”?

Nie utrzymujemy nieskończenie długiej fizycznej sesji.

Utrzymujemy:

text
jeden projekt + stabilny ledger + wiele krótszych sesji


Polityka:

- około 35% kontekstu: checkpoint,
- po zakończeniu zadania: checkpoint,
- około 45% i czysta granica zadania: przejście do świeżej sesji,
- kompresja awaryjna pozostaje zabezpieczeniem, a nie podstawowym sposobem prowadzenia projektu.

Nowa sesja dostaje:

- aktywny task,
- kapsułę,
- wskazane dokumenty,
- aktualny diff/status repozytorium,
- ostatni checkpoint,
- jeden kolejny krok.

Nie potrzebuje pełnych 200 tysięcy tokenów starej historii.

10. Kolejność implementacji

Trzy osobne, możliwe do przeglądu etapy:

1. Hermes core:
- fail-closed checkpoint contract,
- testy, że nie gubi wiadomości i nie zmienia sesji przy awarii.

2. Lokalny provider project-ledger:
- journal,
- Markdown,
- taski,
- bounded prefetch,
- pre/post compression.

3. Proaktywny rollover i opcjonalny context engine:
- automatyczne przechodzenie między krótszymi sesjami,
- później topic-aware select_context() zamiast klasycznej historii.

Nie zaczynałbym od pełnego zastępowania ContextCompressor. To znacznie większe ryzyko. Memory provider plus mały, testowalny backport daje prawie całą potrzebną funkcjonalność przy
mniejszej ingerencji.

Repozytorium Hermesa pozostaje obecnie niezmienione i czyste. Utworzyłem wyłącznie dokumentację planu poza repozytorium. Następny konkretny etap to implementacja punktu 1 na branchu
agent/hermes-project-ledger, po wykonaniu kopii config.yaml, state.db* i zapisaniu obecnego baseline’u.