Releases: electricsheephq/lcm-x
Release list
v0.24.5
v0.24.5 — summaries that can cover every stored row, and an over-window context trimmed of its oldest stored turns before the host sees it (#581, #582, #594)
Qualified at the release candidate tag v0.24.5-rc2 (1b339712): this GA tree is that tree plus this file
(RELEASE-READINESS-V1; git diff --name-status v0.24.5-rc2..v0.24.5 = only this file).
Patch release on top of v0.24.4 (4a9fdd02). Runtime change: what a compaction may summarize, and what the host
receives when a compaction cannot shrink the context.
- No tool name or count, wire format, schema or privacy posture changed.
LCM plugin loadedand everylcm_*name
are unchanged. The only tool-visible change is one new/lcm doctorcheck,survival_fit. - Two new environment switches, both on by default:
LCM_SURVIVAL_FIT(true) andLCM_SURVIVAL_RESERVE(0.15). - Stored rows are never deleted or rewritten by any change below; a survival fit only shortens what the host sends to the
model on that turn. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.4 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #581 (#591): a summary can cover stored rows the host no longer shows.
- A session can hold stored rows the host stopped showing: rows the host compacted in place while native recovery
was ON, and older duplicate copies. The publication proof requires every owned row above the frontier to be
covered, but the summarizer only saw the host view, so every pass ended inpublication_invariant_conflict, the
context stopped shrinking, and a host that fails closed on too little progress reset the session. Nothing was lost. - A leaf's input is now a bounded, contiguous run of the conversation's stored rows in store order, starting after
the frontier. Rows the host shows keep their shown content; rows it does not show are read from the store. The leaf
ends before the first row it cannot account for and never skips it. The proof itself is unchanged. - Ownership is per conversation: one Hermes session can hold rows of several conversations, and a leaf covers only the
bound conversation's rows (plus rows with a blank conversation id and the verified carry). - A tool result whose shown copy did not map is claimed from the store on the next pass.
- A session can hold stored rows the host stopped showing: rows the host compacted in place while native recovery
- #582 (#591): a context that still exceeds the window is trimmed of its oldest stored turns before it reaches the host.
- When a compaction cannot publish (a fault, a lock, a sweep deadline) and the returned list is over the model window,
the oldest whole user turns are dropped from that turn's context until it fits or until nothing stored can leave,
budgeted with the host's own estimator. A newest turn that is over budget on its own gets a bounded projection that names its stored source.
If the fit shortens the list but it is still over budget, the shorter list is returned, a WARNING is logged and
the fit is recorded as not reaching the budget; it is never reported as fitting. If the list holds rows that are
not yet stored, no fit is made and a WARNING is logged. If nothing stored can leave, the list reaches the host
unchanged and no fit is recorded; a warning for that case is tracked in #599. - The notice goes in the system slot, never into the conversation. It logs
LCM survival fit applied, warns once,
and/lcm doctorreports it. Dropped turns stay stored and reachable withlcm_grep/lcm_load_session. - A projected copy that the host later sends back is recognised by its source mark and accepted as that row only
when it equals the projection recomputed from the stored row on every key the projection defines or the store
keeps (role, content, tool_call_id, tool calls with their arguments, the tool name for tool rows); host-private
keys are not compared. A host timestamp on the copy, when present, must match the row's stamp or a recorded alias
stamp, unless the row was stored without one. Otherwise the copy is stored as a new occurrence.
- When a compaction cannot publish (a fault, a lock, a sweep deadline) and the returned list is over the model window,
- #594 (#591): a compaction the host refused no longer leaves the next one conflicting.
- Every host runs the compaction's session end before its would-grow check, and sends no new session start when it
refuses the output. Another agent in the same gateway process (a deferred cleanup, a background review) can also
end the session on the shared lifecycle row. The next publication then read frontier 0 and conflicted. - Compress now re-binds the conversation's lifecycle row when it is unbound, was last finalized by this same session,
and has not been reset since, in one conditional update, so a session that bound in between is never overwritten.
The frontier is restored only from the row. Present since v0.24.0.
- Every host runs the compaction's session end before its would-grow check, and sends no new session start when it
- rc2 — #600: a store-complete leaf never ends on a tool call at the scan cap. When the owned-row scan stops at
its 2,000-row cap inside an open tool group (a call whose results were not all read), the leaf now ends before that
call and reportscut=True; the next leaf starts with the call. On rc1 the leaf could end on the call row, and the
call reached no summary although its row was marked covered (no row loss). One residual shape: #621. (#600, #604) - rc2 — #602: no duplicate reply on a cold resume after a projected user row. After a failed publication whose
survival fit projected the newest user row, rc1's own cold resume of the persisted list stored one duplicate
assistant row. The unstamped replies right after a replayed projection are now recognised as replays of the rows
stored right after its source in the active conversation, in order, while they match exactly; any other row is stored. (#602, #604) - rc2 — #608: a sweep that runs out of time before its first leaf stops instead of raising. A threshold sweep has
a time budget of 120 s. When the work before the first summariser call used it up, the engine raised. Hermes booked
the raise as its own compression stall and ended the turn, and the gateway reset the session although the request
still fitted the window. No stored row was lost. The path is the same in v0.24.3 and v0.24.4.- A spent budget is now a stop: stored leaves are kept, as before; with none,
compress()returns the list
unchanged (statusnoop, stop reasontime_budget_exhausted). No summariser call starts with less than 15 s
left, and the steps before the first call check the deadline. - One WARNING names the seconds per step. Further threshold sweeps of that engine are held for 10 minutes while the
request is below the window minus the survival reserve (85% of the window by default); forced overflow recovery
is not held. - A recovery attempt for a request the provider rejected now comes back under the compaction threshold even when
no leaf could be stored. Before, the host found no progress and the session was reset (an old path). (#608, #617)
- A spent budget is now a stop: stored leaves are kept, as before; with none,
- rc2 — #601 and #603, documentation and doctor. The operator guide gains a "Rollback" section;
/lcm doctor
reports the number of persisted projections (projected_count) and prescribes the backup restore only for those
(a plugin reinstall alone at 0). Both state a condition that is too narrow (#620): the Rollback rule under Upgrade
supersedes the guide and the doctor on that point until v0.24.6. (#601, #603, #604) - Docs and harness:
LCM_SURVIVAL_FITandLCM_SURVIVAL_RESERVEin the README, operator guide and the skill
reference. The reliability harness gains bar B8 (no survival fit in a normal cell) and thenative-on-offcell family
(an older native-ON tree hands the store to the candidate with native OFF). The CHANGELOG line for v0.24.4 now says
thatLCM_IDENTITY_ANCHOR=falserestores the v0.24.3 identity path while the #589 tool-call-id fixes stay active.
Qualification
- rc2 delta, re-scored against the rc1 runtime (the rc2 runtime fixes above; regressions red at
v0.24.5-rc1,
green here): in-process matrix on the 0.21.2 and 0.21.5 hosts, 74 PASS / 12 FAIL at rc1, at the #604 head and at
the #617 head code (identical cells, 0 moves of any kind); replay on copies of the real long-running store
below, at the merged #617 tree with a zero-latency stub summariser, three sessions: 13 at-threshold passes (12 adopted, 1 salvaged), 0 conflicts, 0 over-window requests, 0 rows lost, 0 raises fromcompress(), 0 survival fits; 6 sweeps stopped on the time budget with their leaves kept, each of those passes under 120 s. The rc1 figures that follow were measured at the rc1 runtime. - Reliability gate on real Hermes code, four hosts (0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream),
in-process matrix at the rc1 runtime: 148 PASS / 24 FAIL, and the final review round moved 0 cells. Every FAIL is
#592, a native-ON cell, or a fault-injection cell whose fault never clears. Againstv0.24.4-rc2(measured one
round earlier, on the runtime the final round left unmoved), 0 cells went from PASS to non-PASS and 8 went from
FAIL to PASS: allnative-on-offin-place cells, including the 0.21.2 host'sv0.23.3/in-placecell (#594). - Replay on copies of a real long-running store, at the rc1 runtime (backup-API copies, deleted
afterwards). The host's would-grow guard and session-end order are reproduced, and synthetic turns run up to the
real compaction threshold (204k of a 272k window).- The session wedged since its last summary: 1 at-threshold pass and 18 maintenance passes, all adopted.
- A session holding three conversations: 6 at-threshold passes (1 salvaged, 5 adopted) and 30 maintenance passes
(1 refused, never twice in a row). - Both sessions: 0 conflicts, 0 over-window requests, 0 rows lost, 0 survival fits, and synthetic turns stored
exactly once.
- Review chain on #591, all cross-model (codex gpt-5.6-sol, high): FAIL 42 → FAI...
v0.24.5-rc2
v0.24.5-rc2 — summaries that can cover every stored row, and an over-window context trimmed of its oldest stored turns before the host sees it (#581, #582, #594)
RELEASE CANDIDATE — not GA. This prerelease enters the RELEASE-READINESS-V1 gauntlet
(bench/specs/RELEASE-READINESS-V1.md) at this tag:
- Phase A: the all-tools live matrix on a fresh clone across privacy postures, plus the planted-secret battery. Identity
is bound tohermes-lcm-x v0.24.5 (15 tools). - Phase B: a P0/P1 sweep of the full
v0.24.4→rc diff, including the upgrade and rollback path. - Phase C: a live
hermes acpsoak of 30+ turns, native OFF, on Hermesv2026.9.24.
GA follows only when all three receipts are green, and the GA tree is this tree plus the v0.24.5 release-notes file.
Patch release on top of v0.24.4 (4a9fdd02). Runtime change: what a compaction may summarize, and what the host
receives when a compaction cannot shrink the context.
- No tool name or count, wire format, schema or privacy posture changed.
LCM plugin loadedand everylcm_*name
are unchanged. The only tool-visible change is one new/lcm doctorcheck,survival_fit. - Two new environment switches, both on by default:
LCM_SURVIVAL_FIT(true) andLCM_SURVIVAL_RESERVE(0.15). - Stored rows are never deleted or rewritten by any change below; a survival fit only shortens what the host sends to the
model on that turn. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.4 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #581 (#591): a summary can cover stored rows the host no longer shows.
- A session can hold stored rows the host stopped showing: rows the host compacted in place while native recovery
was ON, and older duplicate copies. The publication proof requires every owned row above the frontier to be
covered, but the summarizer only saw the host view, so every pass ended inpublication_invariant_conflict, the
context stopped shrinking, and a host that fails closed on too little progress reset the session. Nothing was lost. - A leaf's input is now a bounded, contiguous run of the conversation's stored rows in store order, starting after
the frontier. Rows the host shows keep their shown content; rows it does not show are read from the store. The leaf
ends before the first row it cannot account for and never skips it. The proof itself is unchanged. - Ownership is per conversation: one Hermes session can hold rows of several conversations, and a leaf covers only the
bound conversation's rows (plus rows with a blank conversation id and the verified carry). - A tool result whose shown copy did not map is claimed from the store on the next pass.
- A session can hold stored rows the host stopped showing: rows the host compacted in place while native recovery
- #582 (#591): a context that still exceeds the window is trimmed of its oldest stored turns before it reaches the host.
- When a compaction cannot publish (a fault, a lock, a sweep deadline) and the returned list is over the model window,
the oldest whole user turns are dropped from that turn's context until it fits or until nothing stored can leave,
budgeted with the host's own estimator. A newest turn that is over budget on its own gets a bounded projection that names its stored source.
If the fit shortens the list but it is still over budget, the shorter list is returned, a WARNING is logged and
the fit is recorded as not reaching the budget; it is never reported as fitting. If the list holds rows that are
not yet stored, no fit is made and a WARNING is logged. If nothing stored can leave, the list reaches the host
unchanged and no fit is recorded; a warning for that case is tracked in #599. - The notice goes in the system slot, never into the conversation. It logs
LCM survival fit applied, warns once,
and/lcm doctorreports it. Dropped turns stay stored and reachable withlcm_grep/lcm_load_session. - A projected copy that the host later sends back is recognised by its source mark and accepted as that row only
when it equals the projection recomputed from the stored row on every key the projection defines or the store
keeps (role, content, tool_call_id, tool calls with their arguments, the tool name for tool rows); host-private
keys are not compared. A host timestamp on the copy, when present, must match the row's stamp or a recorded alias
stamp, unless the row was stored without one. Otherwise the copy is stored as a new occurrence.
- When a compaction cannot publish (a fault, a lock, a sweep deadline) and the returned list is over the model window,
- #594 (#591): a compaction the host refused no longer leaves the next one conflicting.
- Every host runs the compaction's session end before its would-grow check, and sends no new session start when it
refuses the output. Another agent in the same gateway process (a deferred cleanup, a background review) can also
end the session on the shared lifecycle row. The next publication then read frontier 0 and conflicted. - Compress now re-binds the conversation's lifecycle row when it is unbound, was last finalized by this same session,
and has not been reset since, in one conditional update, so a session that bound in between is never overwritten.
The frontier is restored only from the row. Present since v0.24.0.
- Every host runs the compaction's session end before its would-grow check, and sends no new session start when it
- rc2 — #600: a store-complete leaf never ends on a tool call at the scan cap. When the owned-row scan stops at
its 2,000-row cap inside an open tool group (a call whose results were not all read), the leaf now ends before that
call and reportscut=True; the next leaf starts with the call. On rc1 the leaf could end on the call row, and the
call reached no summary although its row was marked covered (no row loss). (#600, #604) - rc2 — #602: no duplicate reply on a cold resume after a projected user row. After a failed publication whose
survival fit projected the newest user row, rc1's own cold resume of the persisted list stored one duplicate
assistant row. The unstamped replies right after a replayed projection are now recognised as replays of the rows
stored right after its source in the active conversation, in order, while they match exactly; any other row is stored. (#602, #604) - rc2 — #608: a sweep that runs out of time before its first leaf stops instead of raising. A threshold sweep has
a time budget of 120 s. When the work before the first summariser call used it up, the engine raised. Hermes booked
the raise as its own compression stall and ended the turn, and the gateway reset the session although the request
still fitted the window. No stored row was lost. The path is the same in v0.24.3 and v0.24.4.- A spent budget is now a stop: stored leaves are kept, as before; with none,
compress()returns the list
unchanged (statusnoop, stop reasontime_budget_exhausted). No summariser call starts with less than 15 s
left, and the steps before the first call check the deadline. - One WARNING names the seconds per step. Further threshold sweeps of that engine are held for 10 minutes while the
request is below the window minus the survival reserve (85% of the window by default); forced overflow recovery
is not held. - A recovery attempt for a request the provider rejected now comes back under the compaction threshold even when
no leaf could be stored. Before, the host found no progress and the session was reset (an old path). (#608, #617)
- A spent budget is now a stop: stored leaves are kept, as before; with none,
- rc2 — #601 and #603, documentation and doctor. The operator guide gains a "Rollback" section (the wording under
Upgrade below);/lcm doctorreports the number of persisted projections (projected_count) and prescribes the
backup restore only for those (a plugin reinstall alone stays supported at 0). (#601, #603, #604) - Docs and harness:
LCM_SURVIVAL_FITandLCM_SURVIVAL_RESERVEin the README, operator guide and the skill
reference. The reliability harness gains bar B8 (no survival fit in a normal cell) and thenative-on-offcell family
(an older native-ON tree hands the store to the candidate with native OFF). The CHANGELOG line for v0.24.4 now says
thatLCM_IDENTITY_ANCHOR=falserestores the v0.24.3 identity path while the #589 tool-call-id fixes stay active.
Qualification
- rc2 delta, re-scored against the rc1 runtime (the rc2 runtime fixes above; regressions red at
v0.24.5-rc1,
green here): in-process matrix on the 0.21.2 and 0.21.5 hosts, 74 PASS / 12 FAIL at rc1, at the #604 head and at
the #617 head code (identical cells, 0 moves of any kind); replay on copies of the real long-running store
below, at the merged #617 tree with a zero-latency stub summariser, three sessions: 13 at-threshold passes (12 adopted, 1 salvaged), 0 conflicts, 0 over-window requests, 0 rows lost, 0 raises fromcompress(), 0 survival fits; 6 sweeps stopped on the time budget with their leaves kept, each of those passes under 120 s. The rc1 figures that follow were measured at the rc1 runtime. - Reliability gate on real Hermes code, four hosts (0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream),
in-process matrix at the rc1 runtime: 148 PASS / 24 FAIL, and the final review round moved 0 cells. Every FAIL is
#592, a native-ON cell, or a fault-injection cell whose fault never clears. Againstv0.24.4-rc2(measured one
round earlier, on the runtime the final round left unmoved), 0 cells went from PASS to non-PASS and 8 went from
FAIL to PASS: allnative-on-offin-place cells, including the 0.21.2 host'sv0.23.3/in-placecell (#594). - Replay on copies of a real long-running store, at the rc1 runtime (backup-API copies, deleted
afterwards). The host's would-grow guard and session-end order are reproduced, and synthetic turns run up to the
real compaction threshold (204k of a 272k window).- The session wedged since its last summary: 1 at-threshold pass and 18 maintenance passes, all adopted.
- A session holding three conversations: 6 at-threshold...
v0.24.5-rc1
v0.24.5-rc1 — summaries that can cover every stored row, and an over-window context trimmed of its oldest stored turns before the host sees it (#581, #582, #594)
RELEASE CANDIDATE — not GA. This prerelease enters the RELEASE-READINESS-V1 gauntlet
(bench/specs/RELEASE-READINESS-V1.md) at this tag:
- Phase A: the all-tools live matrix on a fresh clone across privacy postures, plus the planted-secret battery. Identity
is bound tohermes-lcm-x v0.24.5 (15 tools). - Phase B: a P0/P1 sweep of the full
v0.24.4→rc diff, including the upgrade and rollback path. - Phase C: a live
hermes acpsoak of 30+ turns, native OFF, on Hermesv2026.9.24.
GA follows only when all three receipts are green, and the GA tree is this tree plus the v0.24.5 release-notes file.
Patch release on top of v0.24.4 (4a9fdd02). Runtime change: what a compaction may summarize, and what the host
receives when a compaction cannot shrink the context.
- No tool name or count, wire format, schema or privacy posture changed.
LCM plugin loadedand everylcm_*name
are unchanged. The only tool-visible change is thesurvival_fitcheck in/lcm doctor; the runtime change is the
one named above. - Two new environment switches, both on by default:
LCM_SURVIVAL_FIT(true) andLCM_SURVIVAL_RESERVE(0.15).
/lcm doctorgains one check,survival_fit. - Stored rows are never deleted or rewritten by any change below; a survival fit only shortens what the host sends to the
model on that turn. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.4 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #581 (#591): a summary can cover stored rows the host no longer shows.
- A session can hold stored rows the host stopped showing: rows the host compacted in place while native recovery
was ON, and older duplicate copies. The publication proof requires every owned row above the frontier to be
covered, but the summarizer only saw the host view, so every pass ended inpublication_invariant_conflict, the
context stopped shrinking, and a host that fails closed on too little progress reset the session. Nothing was lost. - A leaf's input is now a bounded, contiguous run of the conversation's stored rows in store order, starting after
the frontier. Rows the host shows keep their shown content; rows it does not show are read from the store. The leaf
ends before the first row it cannot account for and never skips it. The proof itself is unchanged. - Ownership is per conversation: one Hermes session can hold rows of several conversations, and a leaf covers only the
bound conversation's rows (plus rows with a blank conversation id and the verified carry). - A tool result whose shown copy did not map is claimed from the store on the next pass.
- A session can hold stored rows the host stopped showing: rows the host compacted in place while native recovery
- #582 (#591): a context that still exceeds the window is trimmed of its oldest stored turns before it reaches the host.
- When a compaction cannot publish (a fault, a lock, a sweep deadline) and the returned list is over the model window,
the oldest whole user turns are dropped from that turn's context until it fits or until nothing stored can leave,
budgeted with the host's own estimator. A newest turn that is over budget on its own gets a bounded projection that names its stored source.
If the fit shortens the list but it is still over budget, the shorter list is returned, a WARNING is logged and
the fit is recorded as not reaching the budget; it is never reported as fitting. If the list holds rows that are
not yet stored, no fit is made and a WARNING is logged. If nothing stored can leave, the list reaches the host
unchanged and no fit is recorded; a warning for that case is tracked in #599. - The notice goes in the system slot, never into the conversation. It logs
LCM survival fit applied, warns once,
and/lcm doctorreports it. Dropped turns stay stored and reachable withlcm_grep/lcm_load_session. - A projected copy that the host later sends back is recognised by its source mark, recomputed from the stored row,
and accepted as that row only when it equals the recomputed projection on every key the projection defines or the
store keeps (role, content, tool_call_id, tool calls with their arguments, and the tool name for tool rows).
Host-private keys, which the store never holds, are not compared. A copy that carries a host timestamp must also
match the row's stamp or one of its recorded alias stamps, unless the row was stored without a timestamp (a host
that re-stamps the copy); a copy without a timestamp is judged on the keys alone. Otherwise it is stored as a new
occurrence.
- When a compaction cannot publish (a fault, a lock, a sweep deadline) and the returned list is over the model window,
- #594 (#591): a compaction the host refused no longer leaves the next one conflicting.
- Every host runs the compaction's session end before its would-grow check, and sends no new session start when it
refuses the output. Another agent in the same gateway process (a deferred cleanup, a background review) can also
end the session on the shared lifecycle row. The next publication then read frontier 0 and conflicted. - Compress now re-binds the conversation's lifecycle row when it is unbound, was last finalized by this same session,
and has not been reset since, in one conditional update, so a session that bound in between is never overwritten.
The frontier is restored only from the row. Present since v0.24.0.
- Every host runs the compaction's session end before its would-grow check, and sends no new session start when it
- Docs and harness:
LCM_SURVIVAL_FITandLCM_SURVIVAL_RESERVEin the README, operator guide and the skill
reference. The reliability harness gains bar B8 (no survival fit in a normal cell) and thenative-on-offcell family
(an older native-ON tree hands the store to the candidate with native OFF). The CHANGELOG line for v0.24.4 now says
thatLCM_IDENTITY_ANCHOR=falserestores the v0.24.3 identity path while the #589 tool-call-id fixes stay active.
Qualification
- Reliability gate on real Hermes code, four hosts (0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream),
in-process matrix at this release's runtime: 148 PASS / 24 FAIL, and the final review round moved 0 cells. Every
FAIL is #592, a native-ON cell, or a fault-injection cell whose fault never clears. Measured one round earlier, on
the runtime the final round left unmoved: againstv0.24.4-rc2, 0 cells went from PASS to non-PASS and 8 went
from FAIL to PASS. All 8 arenative-on-offin-place cells, including the 0.21.2 host'sv0.23.3/in-placecell,
which the #594 re-bind fixes. - Replay on copies of a real long-running store, at this release's runtime (backup-API copies, deleted
afterwards). The host's would-grow guard and session-end order are reproduced, and synthetic turns run up to the
real compaction threshold (204k of a 272k window).- The session wedged since its last summary: 1 at-threshold pass and 18 maintenance passes, all adopted.
- A session holding three conversations: 6 at-threshold passes (1 salvaged, 5 adopted) and 30 maintenance passes
(1 refused, never twice in a row). - Both sessions: 0 conflicts, 0 over-window requests, 0 rows lost, 0 survival fits, and synthetic turns stored
exactly once.
- Review chain on #591, all cross-model (codex gpt-5.6-sol, high): full review FAIL 42 → round 3 → delta FAIL 48 →
round 4 (self-verifying projection; blank-id probe) → final delta FAIL 72 (a projection accepted without its
timestamp) → round 5 → delta FAIL 62 (a re-stamped copy of an unstamped row; a non-atomic re-bind) → round 6 →
delta confirm PASS 98, no findings. An adversarial invariant workflow (7 skeptics, every claim re-checked
independently) confirmed three more issues, each fixed red-first. - The gauntlet runs AT THE
v0.24.5-rc1TAG, and its three receipts are what the GA notes link:- Phase A, bound to
hermes-lcm-x v0.24.5 (15 tools). - Phase B: a full sweep over
v0.24.4..v0.24.5-rc1, plus hands-on upgrade and rollback on one store
(v0.24.4 → rc → v0.24.4), and the native ON → OFF rehearsal on a v0.23.3 store that the D2 rollout needs. - Phase C, live.
- Phase A, bound to
Known follow-ups and limitations (tracked)
- #485, #542 — duplicates created by earlier versions stay as they are, and nothing deletes rows. Sessions that could
not publish because of #581 publish again on this release. - #588 — on a fresh bind, the replay can map a row's neighbours to a later, incomplete copy set and store the row's own
copies again (duplicates, never a loss; the same on v0.24.4). The fix targets v0.24.6. - #592 — in rotation mode, after switching native recovery ON → OFF, compactions make no progress until a survival fit,
and the next pass then publishes (lossless). In-place mode, the Hermes 0.21.2 default, is unaffected. - #593 — the #583 reservation re-routes a stamped row one step only. No field or harness case is known.
- #541 — under a publication fault that never clears, turns keep failing until it clears (lossless); meanwhile the survival
fit trims each over-window request of its oldest stored turns. A single failure recovers. - #569 — the gateway-process and process-level fault cells of the reliability harness, and the
tool_searchbridge for
Hermes 0.21.2. - #574 — atomicity of the relation writes with their rows.
- #509 native family — with native recovery ON, a short tool-dense prefix is refused (
prefix_too_short) and LCM
does not compact that session (lossless). Native recovery stays OFF by default on Hermes older thanv2026.9.24. - #501 class — a byte-identical re-paste of the session's own summary or objective is stored once more (accepted).
- The row mapper still scans the whole session on every call (performance, not correctness).
- #597 — a large hidden backlog (rows the host no longer shows) drains one bounded leaf per at-threshold pass, so
the view shrinks slowly until it is drained (no ...
v0.24.4
v0.24.4 — message identity anchored on the host timestamp (#436)
Qualified at the release candidate tag v0.24.4-rc3 (7a795ce9): this GA tree is that tree plus this file
(RELEASE-READINESS-V1; git diff --name-status v0.24.4-rc3..v0.24.4 = only this file).
Patch release on top of v0.24.3 (bafd8824). Runtime change: how LCM-X decides that a message the host shows it is
already stored.
- No config key, tool name or count, handler behaviour, wire format or privacy posture changed.
LCM plugin loadedand everylcm_*name are unchanged.- One new environment switch,
LCM_IDENTITY_ANCHOR, defaults on.falserestores the v0.24.3 identity path; the
tool-call-id fixes (#589) stay active either way. - The store gains one additive table (
message_relations) and non-unique indexes. No existing column changes; an existing row changes only where a missingobserved_atis backfilled for a proven
occurrence. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.3 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #590 (since rc2): fixes from the rc2 Phase B sweep.
- A stored row the host shows under a different key than the one LCM recorded is now reserved like any other row
the host shows on its own. Two cases: a row LCM saved before the host stamped it (#583), and a row the host shows
through a timestamp LCM recorded as an alias of it. A later merged row that repeats its text can no longer absorb
it, so the repeated message is stored as its own occurrence. - The reservation stays bounded: each recorded alias adds one stamp, so a row's keys are at most its aliases × its
stored forms.
- A stored row the host shows under a different key than the one LCM recorded is now reserved like any other row
- #589 (since rc2): provider tool-call ids reused across turns (#586, #587).
- Some providers repeat a tool-call id in later turns. When the context bypass trims the oldest tool call, it now
removes only the results that answer that call, not a later turn's result that reuses its id. - With active-replay stubbing enabled (off by default), a result stays inline only when its own call is
lcm_describeorlcm_expand, not when some earlier call used the same id. - Behaviour with distinct ids is unchanged.
- Some providers repeat a tool-call id in later turns. When the context bypass trims the oldest tool call, it now
- #580 (since rc1): fixes from the rc1 Phase B sweep.
- A repeated user message that the host merges into a failed turn (for example
continuetyped twice) is now
stored as its own occurrence. A row the host shows on its own is never used as a piece of a merged row. - v0.24.3 lost the merged message for every text; rc1 had narrowed that to repeated text.
- This check, and the check that finds rows no summary has covered yet, now pair each stored row with what the
host shows through a complete matching. The result no longer depends on the order in which a row's text forms are tried. - The matching is deterministic and bounded: work is linear in rows, occurrences and keys; a hard work budget with a
direct fallback (one warning) caps the worst case. 100,000 identical rows match in well under a second. - A storage rebind now clears the identity caches.
- A repeated user message that the host merges into a failed turn (for example
- #436 (#572): the identity of a message is its host timestamp plus its full content, counted per occurrence.
- Before, LCM-X decided "already stored?" by matching message content as an ordered prefix of the stored session.
- Hermes re-issues its durable rows whenever it copies them: compaction generations, rotation handoff, the ACP
persist replace, and restore. It also merges and rewrites some rows on the way. - So one unmatched row broke the prefix and the whole tail was stored again, which is where the duplicate counts in
#553/#561/#563 came from. - A row the host had merged away was never covered when a summary was published, and the session stopped
compacting. - The host's message timestamp survives every copy path on Hermes 0.21.2, 0.21.5 and upstream, and Hermes itself
uses it as its logical identity. The rules: - Replays are matched per occurrence on the full payload plus the host timestamp. There is no ordered-prefix
dependency. - A row the host merged is absorbed only when it is an exact, unique, ordered decomposition of stored rows. That
proof is recorded inmessage_relations. The stored remainder is byte-exact. - A summary claims a source only when that source's text is in the summarizer input. A row the host no longer shows
is put back into the input from its stored bytes, counted per occurrence. - A missing timestamp is backfilled only for a proven occurrence. A rewrite of the same object keeps the old bytes and
records the new version assupersedes. An unexplained mismatch is kept as a separate row: never dropped, never a
stuck session. - Rotation carry follows only the verified compression-ancestor chain. A sibling session in the same conversation
gets none. - A merge-turn view that carries an LCM tool call is treated as a replay and never blocks publication (#563).
Qualification
- The reliability gate (G-REL-1) is green at the candidate tree (
eb35c3af), measured with the in-repo
reliability harness on real Hermes code on four hosts: 0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream6f7a7991.- In-process: every gate cell PASSES (116/116).
- Over a real
hermes acpprocess: every cell that transport can drive PASSES (82). The 34 cells it cannot drive yet
are tracked in #569 and pass in-process. - 0 cells went from PASS to non-PASS against
v0.24.3. Everyv0.24.3gate FAIL now passes; that covers the cells
targeting #553, #561, #563, #489, #546/#547, #549, #541 (single failure) and #493/#544. - The positive controls (PC-1, PC-2, PC-3) hold.
- The reliability gate was re-run for #580 on the same harness, rc1 against the fixed tree, on all four hosts, and the
gate passes. On the final matching code, the in-process matrix changed 0 cells against rc1 (156 cells). Thehermes acp
process transport was re-run on an earlier round of the fix and changed 0 cells. - The reliability gate was re-run for #590 against rc2 on all four hosts. The in-process matrix changed 0 cells (156
cells; 140 PASS and 16 FAIL on both sides), and the gate passes. #589 changes behaviour only when a provider reuses a
tool-call id. The matrix does not script that shape, so its regressions and distinct-id controls pin it instead. - RELEASE-READINESS-V1 gauntlet AT THE
v0.24.4-rc3TAG (7a795ce9). Receipts are attached to this release as redacted
public copies (SHA256SUMS):- Phase A: PASS. Release identity bound to the tag; 15 tools;
tool matrix 30/30; batteries 4/4. - Phase B, one sweep over the full
bafd8824..v0.24.4-rc3diff
(astra-delta.txt): P0 0, P1 0, P2 0, P3 1 (B-DOC-2, the
flag-off wording, corrected in the opening summary above). Every rc1 and rc2 sweep finding (B-ID-1, B-ID-2, B-ID-3,
#583, B-DOC-1) re-checked FIXED at this tree. - Phase B hands-on (
PHASE-B-HANDSON-RECEIPT.md): upgrade, rollback and re-upgrade on one store, 0 rows re-stored at each restart, multiset 72/72; real
PluginManager tests 32 passed + 4 expected #479 xfails (Hermes 0.21.2 host) and 36 passed (Hermes v2026.9.24);
default-config matrix 8/8 cells; rc3 regression suites 102 passed; downgrade probes P1-prime to P4 pass; with the
anchor off, stored rows equal v0.24.3's exactly. The native-OFF field rehearsal (a v0.23.3 store opened by this
tree on the Hermes 0.21.2 host shape) stopped at its first bar: the fresh bind stored 4 existing rows again (#588:
duplicates, 0 lost, 0 conflicts). The same instrument measures the same on v0.24.3 and on the v0.24.5 candidate;
the rehearsal repeats on v0.24.5, the release that supports switching such stores from
native recovery ON to OFF (#581). - Phase C, lane summary
RESULT-AC.md: PASS on a live Hermes session: 40 turns + 3 probes; 5 compactions committed, 0 aborted, 20 summary
nodes; multiset 88/88, 0 duplicates; 0 publication conflicts; probes 3/3 exact; the restart replayed 0 rows.
- Phase A: PASS. Release identity bound to the tag; 15 tools;
- Review chain on #572, all cross-model (codex gpt-5.6-sol, high): full review FAIL 86 → two findings fixed with
red-first regressions → delta confirm PASS 97 → residuals and thread fixes → residuals review PASS 95. The design
had an independent architecture review before any code (gpt-6-astra, every requested change adopted).
Known follow-ups and limitations (tracked)
- #485, #542 — duplicates and wedged sessions created by earlier versions stay as they are. This release prevents new
ones from the identity shapes above; the repair ships separately (owner-gated; nothing deletes rows). - #581 — a session that holds stored rows the host no longer shows cannot publish a new summary. Those rows are rows the
host compacted in place while native recovery was ON, or older duplicate copies. Every pass then ends in
publication_invariant_conflict; the rows stay stored (lossless), but the live context stops shrinking. Do not
switch a profile from native recovery ON to OFF on this release. The fix (leaves sourced from the store) targets
v0.24.5. - #582 — when a compaction cannot publish, the context is returned unshrunk. On a host that fails closed when compression
makes too little progress, that ends in a sess...
v0.24.4-rc3
v0.24.4-rc3 — message identity anchored on the host timestamp (#436)
RELEASE CANDIDATE — not GA. This prerelease enters the RELEASE-READINESS-V1 gauntlet
(bench/specs/RELEASE-READINESS-V1.md) at this tag:
- Phase A: the all-tools live matrix on a fresh clone across privacy postures, plus the planted-secret battery. Identity
is bound tohermes-lcm-x v0.24.4 (15 tools). - Phase B: a P0/P1 sweep of the full
v0.24.3→rc diff, including the upgrade and rollback path. - Phase C: a live
hermes acpsoak of 30+ turns, native OFF, on Hermesv2026.9.24.
GA follows only when all three receipts are green, and the GA tree is this tree plus the v0.24.4 release-notes file.
Patch release on top of v0.24.3 (bafd8824). Runtime change: how LCM-X decides that a message the host shows it is
already stored.
- No config key, tool name or count, handler behaviour, wire format or privacy posture changed.
LCM plugin loadedand everylcm_*name are unchanged.- One new environment switch,
LCM_IDENTITY_ANCHOR, defaults on.falsereproduces the v0.24.3 behaviour exactly. - The store gains one additive table (
message_relations) and non-unique indexes. No existing column changes; an existing row changes only where a missingobserved_atis backfilled for a proven
occurrence. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.3 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #590 (since rc2): fixes from the rc2 Phase B sweep.
- A stored row the host shows under a different key than the one LCM recorded is now reserved like any other row
the host shows on its own. Two cases: a row LCM saved before the host stamped it (#583), and a row the host shows
through a timestamp LCM recorded as an alias of it. A later merged row that repeats its text can no longer absorb
it, so the repeated message is stored as its own occurrence. - The reservation stays bounded: each recorded alias adds one stamp, so a row's keys are at most its aliases × its
stored forms.
- A stored row the host shows under a different key than the one LCM recorded is now reserved like any other row
- #589 (since rc2): provider tool-call ids reused across turns (#586, #587).
- Some providers repeat a tool-call id in later turns. When the context bypass trims the oldest tool call, it now
removes only the results that answer that call, not a later turn's result that reuses its id. - With active-replay stubbing enabled (off by default), a result stays inline only when its own call is
lcm_describeorlcm_expand, not when some earlier call used the same id. - Behaviour with distinct ids is unchanged.
- Some providers repeat a tool-call id in later turns. When the context bypass trims the oldest tool call, it now
- #580 (since rc1): fixes from the rc1 Phase B sweep.
- A repeated user message that the host merges into a failed turn (for example
continuetyped twice) is now
stored as its own occurrence. A row the host shows on its own is never used as a piece of a merged row. - v0.24.3 lost the merged message for every text; rc1 had narrowed that to repeated text.
- This check, and the check that finds rows no summary has covered yet, now pair each stored row with what the
host shows through a complete matching. The result no longer depends on the order in which a row's text forms are tried. - The matching is deterministic and bounded: work is linear in rows, occurrences and keys; a hard work budget with a
direct fallback (one warning) caps the worst case. 100,000 identical rows match in well under a second. - A storage rebind now clears the identity caches.
- A repeated user message that the host merges into a failed turn (for example
- #436 (#572): the identity of a message is its host timestamp plus its full content, counted per occurrence.
- Before, LCM-X decided "already stored?" by matching message content as an ordered prefix of the stored session.
- Hermes re-issues its durable rows whenever it copies them: compaction generations, rotation handoff, the ACP
persist replace, and restore. It also merges and rewrites some rows on the way. - So one unmatched row broke the prefix and the whole tail was stored again, which is where the duplicate counts in
#553/#561/#563 came from. - A row the host had merged away was never covered when a summary was published, and the session stopped
compacting. - The host's message timestamp survives every copy path on Hermes 0.21.2, 0.21.5 and upstream, and Hermes itself
uses it as its logical identity. The rules: - Replays are matched per occurrence on the full payload plus the host timestamp. There is no ordered-prefix
dependency. - A row the host merged is absorbed only when it is an exact, unique, ordered decomposition of stored rows. That
proof is recorded inmessage_relations. The stored remainder is byte-exact. - A summary claims a source only when that source's text is in the summarizer input. A row the host no longer shows
is put back into the input from its stored bytes, counted per occurrence. - A missing timestamp is backfilled only for a proven occurrence. A rewrite of the same object keeps the old bytes and
records the new version assupersedes. An unexplained mismatch is kept as a separate row: never dropped, never a
stuck session. - Rotation carry follows only the verified compression-ancestor chain. A sibling session in the same conversation
gets none. - A merge-turn view that carries an LCM tool call is treated as a replay and never blocks publication (#563).
Qualification
- The reliability gate (G-REL-1) is green at the candidate tree (
eb35c3af), measured with the in-repo
reliability harness on real Hermes code on four hosts: 0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream6f7a7991.- In-process: every gate cell PASSES (116/116).
- Over a real
hermes acpprocess: every cell that transport can drive PASSES (82). The 34 cells it cannot drive yet
are tracked in #569 and pass in-process. - 0 cells went from PASS to non-PASS against
v0.24.3. Everyv0.24.3gate FAIL now passes; that covers the cells
targeting #553, #561, #563, #489, #546/#547, #549, #541 (single failure) and #493/#544. - The positive controls (PC-1, PC-2, PC-3) hold.
- The reliability gate was re-run for #580 on the same harness, rc1 against the fixed tree, on all four hosts, and the
gate passes. On the final matching code, the in-process matrix changed 0 cells against rc1 (156 cells). Thehermes acp
process transport was re-run on an earlier round of the fix and changed 0 cells. - The reliability gate was re-run for #590 against rc2 on all four hosts. The in-process matrix changed 0 cells (156
cells; 140 PASS and 16 FAIL on both sides), and the gate passes. #589 changes behaviour only when a provider reuses a
tool-call id. The matrix does not script that shape, so its regressions and distinct-id controls pin it instead. - The gauntlet runs AT THE
v0.24.4-rc3TAG, and its three receipts are what the GA notes link:- Phase A, bound to
hermes-lcm-x v0.24.4 (15 tools). - Phase B: a full sweep over
bafd8824..v0.24.4-rc3(the previous GA to this rc). It re-checks every rc1 and rc2
sweep finding at this tree. - Phase B hands-on: upgrade and rollback on one store. v0.24.3 → rc → v0.24.3, checking that v0.24.3 opens a store
that holdsmessage_relationsrows, and that a forced v0.24.3 compaction commits after the rollback. - Phase C, live.
- Phase A, bound to
- Review chain on #572, all cross-model (codex gpt-5.6-sol, high): full review FAIL 86 → two findings fixed with
red-first regressions → delta confirm PASS 97 → residuals and thread fixes → residuals review PASS 95. The design
had an independent architecture review before any code (gpt-6-astra, every requested change adopted).
Known follow-ups and limitations (tracked)
- #485, #542 — duplicates and wedged sessions created by earlier versions stay as they are. This release prevents new
ones from the identity shapes above; the repair ships separately (owner-gated; nothing deletes rows). - #581 — a session that holds stored rows the host no longer shows cannot publish a new summary. Those rows are rows the
host compacted in place while native recovery was ON, or older duplicate copies. Every pass then ends in
publication_invariant_conflict; the rows stay stored (lossless), but the live context stops shrinking. Do not
switch a profile from native recovery ON to OFF on this release. The fix (leaves sourced from the store) targets
v0.24.5. - #582 — when a compaction cannot publish, the context is returned unshrunk. On a host that fails closed when compression
makes too little progress, that ends in a session reset once the context passes the window. The raw rows stay in the
store. The survival fit targets v0.24.5. - #594 — when the host refuses a compaction because the output would grow, LCM's lifecycle row is left unbound, since
the host runs the commit's session end before its size check. The next compaction then ends in
publication_invariant_conflict, until a later output is adopted. The rows stay stored (lossless). This is
present since v0.24.0; the fix targets v0.24.5. - #593 — the #583 reservation re-routes a stamped row one step only. A chain of two stamped rows with overlapping
edge-whitespace forms at one timestamp can still leave a NULL-stamped row unreserved. No field or harness case is
known. - #541 — under a publication fault that never clears, turns keep failing until it clears (lossless). A single
failure recovers. - #569 — the gateway-process and process-level fault cells of the reliability harness, and the
tool_searchbridge for
Hermes 0.21.2. - #574 — atomicity of the relation writes with their rows (two small follow-ups from review).
- #588 — on a fresh bind, the replay can map a row's neighbours to a later, incomplete copy set and store the row's own
copies again (duplicates, never a loss; the same on v0.24.3). The fix targets v0.24.6. - #509 native family — with native recovery ON, a short tool-dense...
v0.24.4-rc2
v0.24.4-rc2 — message identity anchored on the host timestamp (#436)
RELEASE CANDIDATE — not GA. This prerelease enters the RELEASE-READINESS-V1 gauntlet
(bench/specs/RELEASE-READINESS-V1.md) at this tag:
- Phase A: the all-tools live matrix on a fresh clone across privacy postures, plus the planted-secret battery. Identity
is bound tohermes-lcm-x v0.24.4 (15 tools). - Phase B: a P0/P1 sweep of the full
v0.24.3→rc diff, including the upgrade and rollback path. - Phase C: a live
hermes acpsoak of 30+ turns, native OFF, on Hermesv2026.9.24.
GA follows only when all three receipts are green, and the GA tree is this tree plus the v0.24.4 release-notes file.
Patch release on top of v0.24.3 (bafd8824). Runtime change: how LCM-X decides that a message the host shows it is
already stored.
- No config key, tool name or count, handler behaviour, wire format or privacy posture changed.
LCM plugin loadedand everylcm_*name are unchanged.- One new environment switch,
LCM_IDENTITY_ANCHOR, defaults on.falsereproduces the v0.24.3 behaviour exactly. - The store gains one additive table (
message_relations) and non-unique indexes. No existing column changes; an existing row changes only where a missingobserved_atis backfilled for a proven
occurrence. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.3 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #580 (since rc1): fixes from the rc1 Phase B sweep.
- A repeated user message that the host merges into a failed turn (for example
continuetyped twice) is now
stored as its own occurrence. A row the host shows on its own is never used as a piece of a merged row. One
exception remains: a row LCM stored before the host stamped it (#583, below). - v0.24.3 lost the merged message for every text; rc1 had narrowed that to repeated text.
- This check, and the check that finds rows no summary has covered yet, now pair each stored row with what the
host shows through a complete matching. The result no longer depends on the order in which a row's text forms are tried. - The matching is deterministic and bounded: work is linear in rows, occurrences and keys; a hard work budget with a
direct fallback (one warning) caps the worst case. 100,000 identical rows match in well under a second. - A storage rebind now clears the identity caches.
- A repeated user message that the host merges into a failed turn (for example
- #436 (#572): the identity of a message is its host timestamp plus its full content, counted per occurrence.
- Before, LCM-X decided "already stored?" by matching message content as an ordered prefix of the stored session.
- Hermes re-issues its durable rows whenever it copies them: compaction generations, rotation handoff, the ACP
persist replace, and restore. It also merges and rewrites some rows on the way. - So one unmatched row broke the prefix and the whole tail was stored again, which is where the duplicate counts in
#553/#561/#563 came from. - A row the host had merged away was never covered when a summary was published, and the session stopped
compacting. - The host's message timestamp survives every copy path on Hermes 0.21.2, 0.21.5 and upstream, and Hermes itself
uses it as its logical identity. The rules: - Replays are matched per occurrence on the full payload plus the host timestamp. There is no ordered-prefix
dependency. - A row the host merged is absorbed only when it is an exact, unique, ordered decomposition of stored rows. That
proof is recorded inmessage_relations. The stored remainder is byte-exact. - A summary claims a source only when that source's text is in the summarizer input. A row the host no longer shows
is put back into the input from its stored bytes, counted per occurrence. - A missing timestamp is backfilled only for a proven occurrence. A rewrite of the same object keeps the old bytes and
records the new version assupersedes. An unexplained mismatch is kept as a separate row: never dropped, never a
stuck session. - Rotation carry follows only the verified compression-ancestor chain. A sibling session in the same conversation
gets none. - A merge-turn view that carries an LCM tool call is treated as a replay and never blocks publication (#563).
Qualification
- The reliability gate (G-REL-1) is green at the candidate tree (
eb35c3af), measured with the in-repo
reliability harness on real Hermes code on four hosts: 0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream6f7a7991.- In-process: every gate cell PASSES (116/116).
- Over a real
hermes acpprocess: every cell that transport can drive PASSES (82). The 34 cells it cannot drive yet
are tracked in #569 and pass in-process. - 0 cells went from PASS to non-PASS against
v0.24.3. Everyv0.24.3gate FAIL now passes; that covers the cells
targeting #553, #561, #563, #489, #546/#547, #549, #541 (single failure) and #493/#544. - The positive controls (PC-1, PC-2, PC-3) hold.
- The reliability gate was re-run for #580 on the same harness, rc1 against the fixed tree, on all four hosts, and the
gate passes. On the final matching code, the in-process matrix changed 0 cells against rc1 (156 cells). Thehermes acp
process transport was re-run on an earlier round of the fix and changed 0 cells; the rc2 gauntlet re-runs it at this
tag. - The gauntlet runs AT THE
v0.24.4-rc2TAG, and its three receipts are what the GA notes link:- Phase A, bound to
hermes-lcm-x v0.24.4 (15 tools). - Phase B: rc1's full sweep over
bafd8824..v0.24.4-rc1, plus a sweep of the rc1 → rc2 delta. - Phase B hands-on: upgrade and rollback on one store. v0.24.3 → rc → v0.24.3, checking that v0.24.3 opens a store
that holdsmessage_relationsrows, and that a forced v0.24.3 compaction commits after the rollback. - Phase C, live.
- Phase A, bound to
- Review chain on #572, all cross-model (codex gpt-5.6-sol, high): full review FAIL 86 → two findings fixed with
red-first regressions → delta confirm PASS 97 → residuals and thread fixes → residuals review PASS 95. The design
had an independent architecture review before any code (gpt-6-astra, every requested change adopted).
Known follow-ups and limitations (tracked)
- #485, #542 — duplicates and wedged sessions created by earlier versions stay as they are. This release prevents new
ones from the identity shapes above; the repair ships separately (owner-gated; nothing deletes rows). - #581 — a session that holds stored rows the host no longer shows cannot publish a new summary. Those rows are rows the
host compacted in place while native recovery was ON, or older duplicate copies. Every pass then ends in
publication_invariant_conflict; the rows stay stored (lossless), but the live context stops shrinking. Do not
switch a profile from native recovery ON to OFF on this release. The fix (leaves sourced from the store) targets
v0.24.5. - #582 — when a compaction cannot publish, the context is returned unshrunk. On a host that fails closed when compression
makes too little progress, that ends in a session reset once the context passes the window. The raw rows stay in the
store. The survival fit targets v0.24.5. - #541 — under a publication fault that never clears, turns keep failing until it clears (lossless). A single
failure recovers. - #569 — the gateway-process and process-level fault cells of the reliability harness, and the
tool_searchbridge for
Hermes 0.21.2. - #574 — atomicity of the relation writes with their rows (two small follow-ups from review).
- #583 — a stored row LCM saved before the host stamped it, which the host later shows with its timestamp, is not yet
reserved. A later merged row that repeats its text can still absorb it (the same behaviour as rc1 and v0.24.3). A
strict regression test pins it; the fix targets v0.24.5. - #509 native family — with native recovery ON, a short tool-dense prefix is refused (
prefix_too_short) and LCM
does not compact that session (lossless). Native recovery stays OFF by default on Hermes older thanv2026.9.24. - #501 class — a byte-identical re-paste of the session's own summary or objective is stored once more (accepted).
- #538, #531, #532, #534, #540, #545, #506, #507 — unchanged from v0.24.3.
Benchmark boundary
No benchmark or scoring path changed. Identity matching adds one indexed lookup per replayed row, and relation writes
happen only for merged rows, proven supersedes and aliased timestamps. Median wall time per turn measured 0.69–1.08× the v0.24.3 tree in the matrix.
Summarization prompts, recall and the doctor scans are unchanged. v0.24.3 numbers stand.
Upgrade
- Install:
hermes plugins install https://github.com/electricsheephq/lcm-x --force --ref <this tag's sha>for a pinned
install (hermes plugins update hermes-lcm-xre-pins catalog installs only). - Config: no change from v0.24.3. The
message_relationstable and its indexes are created on first use; the schema
version stays 5. Upgrading from v0.23.x (hermes-lcm): do the v0.24.0 migration first (README, "Migrating from
hermes-lcm"). - Rollback to v0.24.3 is a reinstall. The added table is left in place, and v0.24.3 ignores it. Rollback is measured
at this tag (Phase B hands-on) and reported in the GA notes. - Native recovery: hosts without the #479 host fix (older than
v2026.9.24) runLCM_NATIVE_RECOVERY=false, as
before.
v0.24.4-rc1
v0.24.4-rc1 — message identity anchored on the host timestamp (#436)
RELEASE CANDIDATE — not GA. This prerelease enters the RELEASE-READINESS-V1 gauntlet
(bench/specs/RELEASE-READINESS-V1.md) at this tag:
- Phase A: the all-tools live matrix on a fresh clone across privacy postures, plus the planted-secret battery. Identity
is bound tohermes-lcm-x v0.24.4 (15 tools). - Phase B: a P0/P1 sweep of the full
v0.24.3→rc diff, including the upgrade and rollback path. - Phase C: a live
hermes acpsoak of 30+ turns, native OFF, on Hermesv2026.9.24.
GA follows only when all three receipts are green, and the GA tree is this tree plus the v0.24.4 release-notes file.
Patch release on top of v0.24.3 (bafd8824). Runtime change: how LCM-X decides that a message the host shows it is
already stored.
- No config key, tool name or count, handler behaviour, wire format or privacy posture changed.
LCM plugin loadedand everylcm_*name are unchanged.- One new environment switch,
LCM_IDENTITY_ANCHOR, defaults on.falsereproduces the v0.24.3 behaviour exactly. - The store gains one additive table (
message_relations) and non-unique indexes. No existing column or row changes. - This release never moves a deployed pin by itself. A deployment moves only when its operator re-pins it.
Changes since v0.24.3 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #436 (#572): the identity of a message is its host timestamp plus its full content, counted per occurrence.
- Before, LCM-X decided "already stored?" by matching message content as an ordered prefix of the stored session.
- Hermes re-issues its durable rows whenever it copies them: compaction generations, rotation handoff, the ACP
persist replace, and restore. It also merges and rewrites some rows on the way. - So one unmatched row broke the prefix and the whole tail was stored again, which is where the duplicate counts in
#553/#561/#563 came from. - A row the host had merged away was never covered when a summary was published, and the session stopped
compacting. - The host's message timestamp survives every copy path on Hermes 0.21.2, 0.21.5 and upstream, and Hermes itself
uses it as its logical identity. The rules: - Replays are matched per occurrence on the full payload plus the host timestamp. There is no ordered-prefix
dependency. - A row the host merged is absorbed only when it is an exact, unique, ordered decomposition of stored rows. That
proof is recorded inmessage_relations. The stored remainder is byte-exact. - A summary claims a source only when that source's text is in the summarizer input. A row the host no longer shows
is put back into the input from its stored bytes, counted per occurrence. - A missing timestamp is backfilled only for a proven occurrence. A rewrite of the same object keeps the old bytes and
records the new version assupersedes. An unexplained mismatch is kept as a separate row: never dropped, never a
stuck session. - Rotation carry follows only the verified compression-ancestor chain. A sibling session in the same conversation
gets none. - A merge-turn view that carries an LCM tool call is treated as a replay and never blocks publication (#563).
Qualification
- The reliability gate (G-REL-1) is green at the candidate tree (
eb35c3af), measured with the in-repo
reliability harness on real Hermes code on four hosts: 0.21.2, 0.21.5, a downstream-patched 0.21.5 tree and upstream6f7a7991.- In-process: every gate cell PASSES (116/116).
- Over a real
hermes acpprocess: every cell that transport can drive PASSES (82). The 34 cells it cannot drive yet
are tracked in #569 and pass in-process. - 0 cells went from PASS to non-PASS against
v0.24.3. Everyv0.24.3gate FAIL now passes; that covers the cells
targeting #553, #561, #563, #489, #546/#547, #549, #541 (single failure) and #493/#544. - The positive controls (PC-1, PC-2, PC-3) hold.
- The gauntlet runs AT THE
v0.24.4-rc1TAG, and its three receipts are what the GA notes link:- Phase A, bound to
hermes-lcm-x v0.24.4 (15 tools). - Phase B, over
bafd8824..v0.24.4-rc1(the v0.24.3 tag → rc, the whole delta). - Phase B hands-on: upgrade and rollback on one store. v0.24.3 → rc → v0.24.3, checking that v0.24.3 opens a store
that holdsmessage_relationsrows, and that a forced v0.24.3 compaction commits after the rollback. - Phase C, live.
- Phase A, bound to
- Review chain on #572, all cross-model (codex gpt-5.6-sol, high): full review FAIL 86 → two findings fixed with
red-first regressions → delta confirm PASS 97 → residuals and thread fixes → residuals review PASS 95. The design
had an independent architecture review before any code (gpt-6-astra, every requested change adopted).
Known follow-ups and limitations (tracked)
- #485, #542 — duplicates and wedged sessions created by earlier versions stay as they are. This release prevents new
ones; the repair uses the same identity rules and ships separately (owner-gated; nothing deletes rows). - #541 — under a publication fault that never clears, turns keep failing until it clears (lossless). A single
failure recovers. - #569 — the gateway-process and process-level fault cells of the reliability harness, and the
tool_searchbridge for
Hermes 0.21.2. - #574 — atomicity of the relation writes with their rows (two small follow-ups from review).
- #509 native family — with native recovery ON, a short tool-dense prefix is refused (
prefix_too_short) and LCM
does not compact that session (lossless). Native recovery stays OFF by default on Hermes older thanv2026.9.24. - #501 class — a byte-identical re-paste of the session's own summary or objective is stored once more (accepted).
- #538, #531, #532, #534, #540, #545, #506, #507 — unchanged from v0.24.3.
Benchmark boundary
No benchmark or scoring path changed. Identity matching adds one indexed lookup per replayed row, and relation writes
only happen for merged rows. Median wall time per turn measured 0.69–1.08× the v0.24.3 tree in the matrix.
Summarization prompts, recall and the doctor scans are unchanged. v0.24.3 numbers stand.
Upgrade
- Install:
hermes plugins install https://github.com/electricsheephq/lcm-x --force --ref <this tag's sha>for a pinned
install (hermes plugins update hermes-lcm-xre-pins catalog installs only). - Config: no change from v0.24.3. The
message_relationstable and its indexes are created on first use; the schema
version stays 5. Upgrading from v0.23.x (hermes-lcm): do the v0.24.0 migration first (README, "Migrating from
hermes-lcm"). - Rollback to v0.24.3 is a reinstall. The added table is left in place, and v0.24.3 ignores it. Rollback is measured
at this tag (Phase B hands-on) and reported in the GA notes. - Native recovery: hosts without the #479 host fix (older than
v2026.9.24) runLCM_NATIVE_RECOVERY=false, as
before.
v0.24.3
v0.24.3 — a leaf chunk never splits a parallel tool-call group
Qualified at the release candidate tag v0.24.3-rc1 (508f8935): this GA tree is that tree plus this file
(RELEASE-READINESS-V1; git diff --name-status v0.24.3-rc1..v0.24.3 = only this file).
Patch release on top of v0.24.2 (3122e0f9). Runtime change: leaf chunk selection in compaction only — no
default, config key, tool name or count, handler behaviour, wire format or privacy posture changed; the durable
proof stays version 3 on the wire with descriptor_version: 4. LCM plugin loaded and every lcm_* name are
unchanged. This release never moves a deployed pin by itself; a deployment moves only when its operator re-pins it.
Changes since v0.24.2 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #559 (#560): the leaf selector could end a compaction chunk after an assistant row with
tool_calls, or between its sibling
results. The result left outside the summary became an orphan, the host dropped it, and every later compaction in that
session failed withpublication_invariant_conflict. A chunk end inside a tool-call group now moves back to before
the group, or through the whole group when moving back would empty the chunk (that leaf can then exceed the leaf
token budget by the rest of one group). The leaf rescue's last-row fallback uses the same rule. Pre-existing since at
least v0.24.1; rows stayed stored (freeze, not loss). - Docs (#558): the operator guide and README document
LCM_MODEL_THRESHOLDSfor profiles that mix a
200k-token primary route with a 1M-token backup route, and list all four supportedlcm:YAML keys (#554).
Accepted direction (unchanged from v0.24.2): where a shape or alignment rule used to lose or wedge, the row is now
stored — at most one bounded duplicate of generated text (#501 class: identity is content, not occurrence).
Qualification
RELEASE-READINESS-V1 gauntlet AT THE v0.24.3-rc1 TAG (508f8935). Receipts attached to this release as assets (redacted public copies,
SHA256SUMS): Phase A PHASE-A-RECEIPT.md; Phase B PHASE-B-RECEIPT.md (the sweep astra-delta.txt and
PHASE-B-HANDSON-RECEIPT.md are its inputs); Phase C PHASE-C1-RECEIPT.md with the lane summary
RESULT-AC.md.
- Phase A at the tag:
release bound to requested tag v0.24.3-rc1(the tag'splugin.yamldeclares0.24.3); 15 registered tools, registry coverage complete; preflight PASS, tool matrix 30/30 rows (local and cloud-default postures), batteries 4/4 (planted-secret, opt-out, durable-redaction, misconfiguration) on Hermesv2026.9.24(f97608f1). - Phase B at the tag: Astra adversarial sweep of the full diff v0.24.2..v0.24.3-rc1 (
3122e0f9..508f8935): P0 0, P1 0, P2 0, P3 0 across correctness and lossless storage, upgrade and rollback, privacy, performance, the Hermes plugin contract, concurrency and documentation truth.
Hands-on (receipt): one lcm.db taken v0.24.2 to v0.24.3-rc1, back to v0.24.2 and forward again: every compaction committed, each restart re-stored and rewrote 0 rows, 72/72 rows under the multiset bar (its positive control fails as expected), 0 conflicts. The #559 tests pass on the rc (22) and fail on v0.24.2 (18 of 22); a rollback taken right after a leaf that ends at a two-call tool group kept the group whole (0 split groups) and the next compactions committed. Real PluginManager tests pass on Hermes 37aad38c (32 passed, 4 xfailed) and v2026.9.24 (36 passed). The default-config live-shape matrix passes 8/8 cells, each with 160 rows, 0 duplicates and 0 conflicts. - Phase C at the tag: one live ACP cell on Hermes
v2026.9.24(f97608f1), native recovery off, in-place compression,glm-5.3through z.ai with the window pinned at 128,000 tokens: 44 turns (40 material, 3 recall probes, 1 doctor turn), 4 compactions all committed, 0 aborted, 0 conflicts, 16 summary nodes; 88/88 transcript items stored exactly once under the multiset bar and 0 SQL duplicate rows (both positive controls fail as expected); recall probes 3/3 exact; a restart after the first compaction reloaded the same session; an exact re-paste of a summary was stored once as a new user row. The model called tools in parallel in three turns (groups of 5, 3 and 2 calls) and no summary ended inside a group (0 split groups). - Per-fix evidence: the #560 merge receipt lists what that fix ran — the probe on the same parallel-call shape at
v0.24.1,v0.24.2andmain, red-first tests at its base, the focused and full suites, and the lossless harness.
Known follow-ups and limitations (tracked)
- #559 — a session that already froze this way on an earlier version stays frozen after the upgrade (the orphaned
row can no longer be covered); start a new session. The fix prevents new splits. - #553 — if Hermes stops between a compaction and its reply (a crash or restart mid-turn) and the next message is merged into the unanswered one, that session can stop compacting and store rows again on every turn; start a new session to recover. Rows already stored are kept. The fix is tracked in #553 for the next release.
- #501 class — a byte-identical re-paste of the session's own summary or objective is stored once more (accepted).
- #542 — sessions already wedged before #535 need a one-time repair (owner-gated; nothing deletes rows).
- #546 — the second restart in a row after a rotation (composite class; strict xfail).
- #538 — a new user message byte-identical to the host's two-line pruned-skill reload notice, merged behind the
todo snapshot, is not stored; waits for provenance for host-generated scaffold (#534). - #547, #549 — the #524 retry re-store on a T3-shaped list; a repeated dangling prompt with different edge
whitespace (both pre-existing). - #531, #532, #534, #540, #541, #544, #545 — lineage gap-free proof, objective-headed head coverage end, provenance for
recovery rows, folded-carrier lineage, generic second re-store after a failed publication, tail-0 retry alignment,
the 64-cut bound on the durable probe. None is a loss path under the multiset bar; each has a probe or xfail. - #506, #507, #509 — proactive-recall carrier adjacency, rotation carry follow-ups, native summary re-attempt holds.
Benchmark boundary
No benchmark or scoring path changed. Leaf chunk selection adds one linear pass over the candidate rows per
compaction; a chunk can end one tool group earlier than its token budget allows, or later only when a single
group is larger than the budget. Summarization prompts, recall and the doctor scans are unchanged. v0.24.2
numbers stand.
Upgrade
hermes plugins install https://github.com/electricsheephq/lcm-x --force --ref <this tag's sha> for a pinned install
(hermes plugins update hermes-lcm-x re-pins catalog installs only). No config change from v0.24.2. Upgrading from
v0.23.x (hermes-lcm): do the v0.24.0 migration first (README, "Migrating from hermes-lcm").
Rollback to v0.24.2 is a plain reinstall; the durable proof format is unchanged. Measured at this tag (Phase B hands-on), the restart after a rollback re-stored
0 rows and the next v0.24.2 compaction committed. Hosts without the
#479 host fix (older than v2026.9.24) run LCM_NATIVE_RECOVERY=false, as before.
v0.24.3-rc1
v0.24.3-rc1 — a leaf chunk never splits a parallel tool-call group
RELEASE CANDIDATE — not GA. This prerelease enters the RELEASE-READINESS-V1 gauntlet
(bench/specs/RELEASE-READINESS-V1.md) at this tag: Phase A (all-tools live matrix on a fresh clone across
privacy postures, planted-secret battery; identity bound to hermes-lcm-x v0.24.3 (15 tools)), Phase B
(P0/P1 sweep of the full v0.24.2→rc diff including the upgrade and rollback path), Phase C (30+ turn live
hermes acp soak, native OFF, on Hermes v2026.9.24, with turns where the model calls a regular tool and an LCM
tool in parallel). GA follows only with all three receipts green, and the GA tree is this tree plus the v0.24.3
release-notes file. A patch release follows the same rc-first rule as a feature train.
Patch release on top of v0.24.2 (3122e0f9). Runtime change: leaf chunk selection in compaction only — no
default, config key, tool name or count, handler behaviour, wire format or privacy posture changed; the durable
proof stays version 3 on the wire with descriptor_version: 4. LCM plugin loaded and every lcm_* name are
unchanged. This release never moves a deployed pin by itself; a deployment moves only when its operator re-pins it.
Changes since v0.24.2 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #559 (#560): the leaf selector could end a compaction chunk after an assistant row with
tool_calls, or between its sibling
results. The result left outside the summary became an orphan, the host dropped it, and every later compaction in that
session failed withpublication_invariant_conflict. A chunk end inside a tool-call group now moves back to before
the group, or through the whole group when moving back would empty the chunk (that leaf can then exceed the leaf
token budget by the rest of one group). The leaf rescue's last-row fallback uses the same rule. Pre-existing since at
least v0.24.1; rows stayed stored (freeze, not loss). - Docs (#558): the operator guide and README document
LCM_MODEL_THRESHOLDSfor profiles that mix a
200k-token primary route with a 1M-token backup route, and list all four supportedlcm:YAML keys (#554).
Accepted direction (unchanged from v0.24.2): where a shape or alignment rule used to lose or wedge, the row is now
stored — at most one bounded duplicate of generated text (#501 class: identity is content, not occurrence).
Qualification
The gauntlet runs AT THE v0.24.3-rc1 TAG — Phase A bound to hermes-lcm-x v0.24.3 (15 tools), Phase B over
3122e0f9..v0.24.3-rc1 (the v0.24.2 tag → rc, whole delta) plus hands-on upgrade/rollback, Phase C live — and its
three receipts are what the GA notes link.
- Phase A, Phase B (sweep and hands-on) and Phase C are measured at this tag; the GA notes link their receipts.
- Phase B hands-on: upgrade v0.24.2 → rc → v0.24.2 on one store (restart re-store counts, the rollback restart
accepting the version-3 record, a forced v0.24.2 compaction committed), real PluginManager identity tests on the
hosts37aad38candv2026.9.24, and the default-config live-shape matrix (8 cells). - Phase C: one live Hermes ACP cell, native OFF in-place on
v2026.9.24, at least two committed compactions, at
least one compaction whose leaf budget ends inside a parallel tool-call group, the multiset lossless bar with a
frozen positive control, the SQL duplicate counter at 0 with a positive control, 0 publication conflicts, 3/3 exact
recall probes, and a restart mid-session. - Per-fix evidence: the #559 merge receipt lists the probe (the same parallel-call shape on
v0.24.1,v0.24.2
andmain), red-first tests at its base, the focused and full suites, and the lossless harness.
Known follow-ups and limitations (tracked)
- #559 — a session that already froze this way on an earlier version stays frozen after the upgrade (the orphaned
row can no longer be covered); start a new session. The fix prevents new splits. - #553 — if Hermes stops between a compaction and its reply (a crash or restart mid-turn) and the next message is merged into the unanswered one, that session can stop compacting and store rows again on every turn; start a new session to recover. Rows already stored are kept. The fix is tracked in #553 for the next release.
- #501 class — a byte-identical re-paste of the session's own summary or objective is stored once more (accepted).
- #542 — sessions already wedged before #535 need a one-time repair (owner-gated; nothing deletes rows).
- #546 — the second restart in a row after a rotation (composite class; strict xfail).
- #538 — a new user message byte-identical to the host's two-line pruned-skill reload notice, merged behind the
todo snapshot, is not stored; waits for provenance for host-generated scaffold (#534). - #547, #549 — the #524 retry re-store on a T3-shaped list; a repeated dangling prompt with different edge
whitespace (both pre-existing). - #531, #532, #534, #540, #541, #544, #545 — lineage gap-free proof, objective-headed head coverage end, provenance for
recovery rows, folded-carrier lineage, generic second re-store after a failed publication, tail-0 retry alignment,
the 64-cut bound on the durable probe. None is a loss path under the multiset bar; each has a probe or xfail. - #506, #507, #509 — proactive-recall carrier adjacency, rotation carry follow-ups, native summary re-attempt holds.
Benchmark boundary
No benchmark or scoring path changed. Leaf chunk selection adds one linear pass over the candidate rows per
compaction; a chunk can end one tool group earlier than its token budget allows, or later only when a single
group is larger than the budget. Summarization prompts, recall and the doctor scans are unchanged. v0.24.2
numbers stand.
Upgrade
hermes plugins install https://github.com/electricsheephq/lcm-x --force --ref <this tag's sha> for a pinned install
(hermes plugins update hermes-lcm-x re-pins catalog installs only). No config change from v0.24.2. Upgrading from
v0.23.x (hermes-lcm): do the v0.24.0 migration first (README, "Migrating from hermes-lcm").
Rollback to v0.24.2 is a plain reinstall; the durable proof format is unchanged. The re-store count after a rollback
restart is measured at this tag (Phase B hands-on) and reported in the GA notes. Hosts without the
#479 host fix (older than v2026.9.24) run LCM_NATIVE_RECOVERY=false, as before.
v0.24.2
v0.24.2 — the post-v0.24.1 fix train: compaction retries resume from the committed frontier, replays of superseded outputs bind as replays, forced-overflow recovery never returns an empty transcript
Qualified at the release candidate tag v0.24.2-rc1 (f60b74f3): this GA tree is that tree plus this file
(RELEASE-READINESS-V1; git diff --name-status v0.24.2-rc1..v0.24.2 = only this file).
Patch release on top of v0.24.1 (98ac62fe). Runtime change: replay reconciliation and forced-overflow recovery
and one tool schema — no default, config key, tool name or count, handler behaviour, wire format or privacy posture
changed; lcm_compile_evidence drops its top-level allOf from its input schema (#550); the durable proof stays
version 3 on the wire with descriptor_version: 4 (#517). LCM plugin loaded and every lcm_* name are unchanged. This release never
moves a deployed pin by itself; a deployment moves only when its operator re-pins it.
Changes since v0.24.1 (every change issue-first, reviewed at its exact head, receipted on its PR)
- #457 (#525): a compaction that the host cancels after LCM committed its first leaf no longer re-summarizes the
covered prefix on every retry (which ended inpublication_invariant_conflictuntil rotation): the retry resumes
from the committed frontier, consuming only this session's committed summary lineage; rows outside that lineage are
preserved in place, never consumed; the token estimate is discounted on resume. - #524 (#527): a session that already adopted one compaction and then retries a cancelled second one binds the
replay of the superseded output as a replay, not as new rows (before: the retry ingest re-stored every replayed row
once, then the retry failed its publication). The head predicate admits only proven emissions — a DAG-verified
summary, an objective row that re-renders a stored own-session row, a system row with the exact LCM note — never a
head that carries tool calls; a prefix-only match keeps its full identity and is stored. - #526 (#530): the same retry inside a rotation child binds against the child's durable lineage — own-session
alignment first, lineage only when fewer than two own fits exist, the smaller cursor wins; any repeated-content
ambiguity falls to the duplicate direction (#531, #532 filed). - #91 (#528) and #529 (#533): forced-overflow recovery never returns an empty transcript and never a system-only
list. Selection: the newest user row that fits under the cap, else the newest non-tool row with its tool pair
tried first, else the smallest over-cap user row, else the smallest row, else a user-role placeholder (Anthropic
hoists system rows out ofmessages); an over-cap newest user turn is announced by a cap-checked note instead of
disappearing silently. (#529 item 3, provenance for recovery rows, moved to #534; item 1 to #529 follow-up.) - #516 (#536): the replay identity cuts only the Hermes todo-annotation span (blank-line-bounded items, an open
item's status suffix, the notice block consumed once, a header-only span) instead of truncating everything after the
todo header, so a user row the host merges behind the annotation is stored; exactly one host delimiter is cut at
both sites and a model-switch prefix on the suffix is stripped under the same rule. - #514 (#539): prior-proof consumption is hardened — projection declines are pre-filtered strictly (duplicate
direction only), a malformed durable proof is caught and a fresh proof recorded, and the proof binding is one
helper (the rotation parent'ssource_bindingis deliberately untouched). - #535 (#543): a host merge-append behind the retained last user row aligns in both walks (the last-position
composite match in the in-process and durable walks, a coverage insert with ownership fail-closed, a raw-first
collapse), so the session no longer wedges into a re-store loop at its first ingest after adoption (#542 tracks
already-wedged sessions). - #519 (#548): after a rotation restart that lands before the last carried prompt is answered, the empty child no longer re-stores the whole restored list and then fails its publication: the durable walk accepts the host's replacement of that final carried user row (R1: digest equal to the parent row at the end of the carry range, no child rows after the last store, the range end trimmed by one in the child's own proof record), voids stale carry ranges on the cursor-0 fallback so the worst case is one bounded duplicate rather than an error plus a second re-store (R2), and the publication-conflict warning now carries the exception detail (R3). Reviewer-found residuals: #546 (second restart composite), #549 (edge-whitespace re-prompt, pre-existing).
- #550 (#551):
lcm_compile_evidencedeclared a top-levelallOf, which Anthropic's API rejects, so a request carrying
the lcm-x tool list failed with HTTP 400 on Anthropic routes since v0.21.0-rc2. TheallOfis removed; the rule it
stated (proposal mode needs aproposal) was already enforced by the handler, so behaviour is unchanged. Measured on
one Anthropic route: the same request returned HTTP 400 at the base and HTTP 200 at the fix. Bedrock, Vertex and other
providers' schema rules were not probed. - #513 (#537, test-only): the
LCM_TEST_HERMES_AGENT_ROOTopt-in no longer leaks the real host import into later
test modules (child-process helper pinned by content hash). - Docs (#523): the README and operator guide say how a
--ref-pinned install moves to a new commit.
Accepted direction (unchanged from v0.24.1): where a shape or alignment rule used to lose or wedge, the row is now
stored — at most one bounded duplicate of generated text (#501 class: identity is content, not occurrence).
Reviewer-found residuals of that class on #530, #533, #543 and #548 were each probed against main under the
multiset lossless bar (store ⊇ host list, 0 missing identities in every cell; head equal to or better than main) and
are disclosed on their PRs.
Qualification
RELEASE-READINESS-V1 gauntlet AT THE v0.24.2-rc1 TAG (f60b74f3). Receipts attached to this release as assets (redacted public copies,
SHA256SUMS): Phase A PHASE-A-RECEIPT.md; Phase B PHASE-B-RECEIPT.md, astra-delta.txt and
PHASE-B-HANDSON-RECEIPT.md; Phase C PHASE-C1-RECEIPT.md with the lane summary
RESULT-AC.md.
- Phase A at the tag:
release bound to requested tag v0.24.2-rc1(the tag'splugin.yamldeclares0.24.2); 15 registered tools, registry coverage complete; preflight PASS, tool matrix 30/30 rows (local and cloud-default postures), batteries 4/4 (planted-secret, opt-out, durable-redaction, misconfiguration) on Hermesv2026.9.24(f97608f1). - Phase B at the tag: P0 0 and P1 0 introduced by this release. The adversarial sweep of the full diff v0.24.1..v0.24.2-rc1 raised one P1-severity shape (B-INT-1: a persist step that replaces a retained-row composite an LCM tool call already ingested, native recovery off). A base-vs-head probe, run under a rule declared before it ran, shows the shape is pre-existing on v0.24.1: the same compaction errors in both persist-step cells (the rotation control errors there but compacts here), 5 duplicate rows per persist cell there against 0 here, and no row lost on either tree. It is therefore reclassified as not a finding of this release; the defect is tracked as #553.
Hands-on (receipt): one lcm.db taken v0.24.1 to v0.24.2-rc1, back to v0.24.1 and forward again: every compaction committed, each restart re-stored and rewrote 0 rows, 72/72 rows under the multiset bar (its positive control fails as expected), 0 conflicts. Real PluginManager tests pass on Hermes 37aad38c (32 passed, 4 xfailed) and v2026.9.24 (36 passed). The default-config live-shape matrix passes 8/8 cells, each with 160 rows, 0 duplicates and 0 conflicts. - Phase C at the tag: one live ACP cell on Hermes
v2026.9.24(f97608f1), native recovery off, in-place compression,glm-5.3through z.ai: 44 turns (40 material, 3 recall probes, 1 doctor turn), 5 compactions all committed, 0 aborted, 0 conflicts, 21 summary nodes; 88/88 transcript items stored exactly once under the multiset bar and 0 SQL duplicate rows (both positive controls fail as expected); recall probes 3/3 exact; a restart after the first compaction reloaded the same session; an exact re-paste of a summary was stored once as a new user row. A first attempt measured nothing because the test window was unpinned (the host readglm-5.3as a 1M-token window from models.dev, so no compaction triggered); the passing attempt pins 128,000 tokens. - Per-fix evidence: each merge receipt (#525, #527, #528, #530, #533, #536, #537, #539, #543, #548, #551) lists what
that fix ran — red-first tests at its base and the focused and full suites for all of them; the rotation harness
and the rollback proof only where its receipt says so (#514 ...