Conversation
Every evolution cycle adds one row to two memory indexes and trims them back to their cap. The trim half has been mechanised for a while (`scripts/archive-memory-index.py`, which picks the OLDEST row by the timestamp in its filename, never by position). The insert half was still hand-written, and it has now failed the same way three times: * the session index is written newest-first while the evolution index is written oldest-first, so a row appended to the end of the session index is the row of the *oldest* cycle in the file; * two cycles reported "move by position" bugs in their own index scripts; * measured 2026-09-14 (cyc20260914-180702): an insert-then-trim one-liner dropped the ten rows it was supposed to keep and left only the new one, and the session index had to be rebuilt from the rows the daemon embeds in its requests. Every one of those is a position where an id was meant. So this tool refuses to ask where a row goes: * the order is read from the index, from the cycle ids of its own rows — ids ascending down the file means append, descending means insert above the first row; an index whose rows are not consistently ordered is not a guess the tool makes, it exits 2 and names them; * the row is placed by id, so re-inserting an older cycle's row lands where that cycle belongs instead of at the front; * the trim is delegated to `archive-memory-index.py` (one implementation of "oldest", with its own conservation check), and the result is verified after the fact: the new row is still there and the index is within its cap; * the index is backed up before it is touched, and any failure leaves the original file exactly as it was. Exit codes keep "clean" and "could not measure" distinct: 1 is a rule violation (that cycle id is already in the index), 2 is a question the tool cannot answer. Tests: tests/test_insert_memory_index_row.py — 15 passed.
|
Closing on the host's ruling: the premise this PR was built on is not needed. The host's ruling (2026-09-14, verbatim): "#1230 是在干什么?'Every evolution cycle inserts one row into two memory indexes' 这个完全不需要。不需要有这个动作。agent session自己会按需记忆的。" That sentence is this PR's whole justification — the tool's docstring opens with it, and the script exists only to mechanise it. An agent session remembering on its own terms does not need a per-cycle, per-index insert action at all, so there is nothing here worth maintaining. Closed, not merged. For the record, in case the ruling is ever revisited: the script inserted a cycle row by cycle id (reading the index's own id order rather than asking the caller for a position), delegated the trim to |
What
scripts/insert-memory-index-row.py+tests/test_insert_memory_index_row.py.Every evolution cycle inserts one row into two memory indexes and trims them back to their cap (50). The trim half has been mechanised for a while (
scripts/archive-memory-index.py, which picks the oldest row by the timestamp in its filename, never by position). The insert half was still hand-written, and it has now failed the same way three times:cyc20260914-180702): an insert-then-trim one-liner dropped the ten rows it was supposed to keep and left only the new one — the session index had to be rebuilt from the rows the daemon embeds in its requests.Every one of those is a position where an id was meant.
How it works
2and names them.archive-memory-index.py(one implementation of "oldest", with its own conservation check), and the result is verified after the fact: the new row is still there and the index is within its cap.1is a rule violation (that cycle id is already in the index),2is a question the tool cannot answer — no file at that path, an inconsistently ordered index, a row that carries no cycle id.Tests
tests/test_insert_memory_index_row.py— 15 passed. Full suite on this head: 1995 passed, 2 skipped, plus the known environmentaltest_check_node_test_count.py::test_real_tree_is_consistentfailure whennpmis not onPATH.