Repository navigation
fix(memory): a maintenance row is audit material, not the owner's speech - #187
Merged
Merged
Conversation
`lifecycle/l0_sweep.py::_journal` captured its own summary without a raw_type,
so `classify_raw` fell through to `user-message` for `cleaner_summary: {...}`.
`graph_enrich`'s junk re-capture did the same for a deleted node's prose — and
`classify_raw` only anchors the opening, so prose with `[ariel recall]` in the
middle was also read as speech. From there the row was treated as a turn:
`graph_miners` clustered it, `l2_enrich` bound it to a session, segmentation used
it as a conversation boundary, and a named replay distilled it into L3/L4.
Both writers now pass an explicit `SERVICE_RAW_TYPE = "service"`, and every
consumer that classifies L0 rows handles it:
- replay's window query skips service rows. The distiller already refuses a
machine report by text, but a structural fact must not depend on a content
detector — and every nightly pass was claiming the sweep row before
discarding it;
- replay's `ids` branch REFUSES a named service row and counts it in
`refused_service`. Naming an id overrides the gate, not the row's nature:
the human keeps the ability to wake a real row, and gets a number and a
warning instead of silence, so a mistyped id from a journal dump is visible
rather than indistinguishable from "already verdicted". The refusal happens
before the claim, so the row's status is untouched;
- `segment_consolidation` skips service rows — a maintenance row is a boundary
the owner never spoke;
- `sweep_received` skips them (a journal-only line has no memory evidence to
find, so judging it would stamp UNACCOUNTED_EXIT for a write that was never
meant to happen); `close_overdue_received` still closes them by TTL, so they
cannot accumulate.
Correcting the audit that prompted this: the pollution is HISTORICAL, not
growing. `shared/machine_report.py` (6617282, 29.7 d ago) already refused
`cleaner_summary:` in the distiller, and the newest such episode is 30.2 d old.
What stayed broken is the classification — graph, session binding and
segmentation kept reading the row as a turn — plus the `graph_cleanup` re-capture
of prose that the text guard does not recognise.
Existing rows are untouched: cleaning 21/9/0 episodes and 21/9/0 graph nodes is
an owner decision, not part of this package.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что
lifecycle/l0_sweep.py::_journalписал свою сводку безraw_type, поэтомуclassify_rawотдавалuser-messageдляcleaner_summary: {...}.graph_enrichпри чистке мусора делал то же с прозой удалённого узла — аclassify_rawякорит только начало строки, так что проза с[ariel recall]в середине тоже читалась как речь.Дальше строка жила как реплика:
graph_minersкластеризовал её,l2_enrichпривязывал к сессии, сегментация считала границей разговора, а replay по явному id дистиллировал в L3/L4.Фикс
Оба служебных писателя ставят
SERVICE_RAW_TYPE = "service", и каждый потребитель, который классифицирует строки L0, его учитывает:features/replay.pyокноfeatures/replay.pyidsrefused_service, до claim — статус строки не трогаетсяlifecycle/segment_consolidation.pylifecycle/graph_miners.py,features/l2_enrich.pyuser-message— service отсекается самshared/l0.py::sweep_receivedUNACCOUNTED_EXITlifecycle/l0_tiers.py::close_overdue_receivedsweep_receivedэто единственный closer, накопления нетidsотказывает видимо, а не молча:processed=0, skipped=0неотличимо от «уже обработана», и человек продолжал бы повторять id, который не может проиграться никогда. Warning называет счётчик.Поправка к аудиту, который это инициировал
Порча историческая, не растущая.
shared/machine_report.py(коммит6617282, 29.7 дня назад) уже отказывалcleaner_summary:в дистилляторе, и новейший такой эпизод — 30.2 дня. По данным verifier'а фактическим блокиратором был importance-гейт (все строки после guard ушли вgated_outсimportance_gate_bypass), а неmachine_report(отказов 0/0/0).Что оставалось сломанным: классификация — граф, привязка к сессиям и сегментация продолжали читать строку как реплику, — плюс рекапча прозы
graph_cleanup, которую текстовый guard не распознаёт.Проверка
replay(ids=…)обходил фильтр и доказал её end-to-end (1 эпизод + 1 узел). Второй круг: 18/18 PASS, дефектов нет; отдельно проверено — смешанныйids,idsтолько из service, несуществующий id, staleprocessing, совместимость с вызывающими.Ответ verifier'а: «Can a service row still become speech on ANY path? — NO».
Остаётся
Существующие строки не тронуты: 21/9/0 эпизодов и 21/9/0 узлов в Hermes/Mimocode/CowAgent. Чистка — отдельное решение владельца.
Остаточный риск: гарантия типовая. Писатель, забывший
raw_type, снова получитuser-message; на живой базе таких строк сейчас 0.