Skip to content

fix: share LCM storage across runtime clones - #202

Closed
100yenadmin wants to merge 4 commits into
mainfrom
upstream/pr-506
Closed

100yenadmin wants to merge 4 commits into
mainfrom
upstream/pr-506

Conversation

@100yenadmin

Copy link
Copy Markdown
Member

Important

This executable LCM-X PR was recreated by the migration operator from the exact upstream commit head. GitHub did not transfer the original PR actor, dates, review objects, or approval state.

Source and attribution

@coderabbitai ignore

Original commit authorship and history remain in the commits. Historical discussion and review text are imported below as attributed ordinary comments; they are not new approvals or change requests.

Original upstream PR description

Summary

  • Add a reference-counted _StorageBundle for the SQLite helpers shared by cloned LCM runtimes.
  • Adopt the shared bundle in clone_for_agent() and release it during shutdown, while preserving per-agent session state.
  • Add FD-hygiene coverage for 50 clones and update clone identity assertions.
  • Make the plugin test bootstrap locate the Hermes host module from a standalone worktree.

This is the distinct LCM storage-lifecycle half of the descriptor-lifecycle work. It is not the generic SessionDB fix in hermes-agent#72822.

Tracking

  • hermes-agent#79537 — descriptor-lifecycle implementation
  • hermes-agent#79538 — plugin packaging
  • hermes-agent#72782 — parent work item
  • Distinct from hermes-agent#72822 — generic SessionDB fix

Verification

  • python3 -m pytest -q tests/test_fd_hygiene.py — 1 passed
  • python3 -m pytest -q tests/test_lcm_core.py — 308 passed
  • python3 -m compileall -q engine.py tests/test_fd_hygiene.py tests/test_lcm_core.py — passed
  • git diff --check — passed

Scope

Fresh branch from origin/main; only engine.py, tests/conftest.py, tests/test_lcm_core.py, and tests/test_fd_hygiene.py are included. No generated files or unrelated existing work are included.

@100yenadmin

Copy link
Copy Markdown
Member Author

Imported upstream pr-conversation

@​stephenschoettler maintainer review requested. The repository owner and recent merger of the latest releases/fixes, you appear to be the appropriate reviewer for this PR.

Please review the _StorageBundle ownership/refcounting, run or enable CI, and advise whether the dependency on hermes-agent PR #79575 should be handled as-is or adjusted before merge.


Imported upstream pr-conversation

Pre-review finding (likely blocker): clone_for_agent() calls _adopt_storage_bundle() before constructing the optional AdaptiveRetrievalRegistry and ModelAssertionExtractor. If either constructor raises, the partially constructed clone is not shut down/released, leaving _StorageBundle._refs elevated and leaking the shared storage lifetime. Please wrap post-adoption clone initialization in try/except and call clone.shutdown() (or release the bundle directly) before re-raising; add a regression test that forces each optional constructor to fail and asserts the prototype refcount returns to its prior value.


Imported upstream pr-conversation

Additional pre-review blocker: this branch appears not to implement the explicit ContextEngine.create_runtime() / close() contract introduced by hermes-agent PR #79575. Once that core loader contract is active, the LCM engine may be rejected for lacking an isolated runtime factory, and inherited close() will not release the shared storage bundle. The plugin PR should implement the contract explicitly, likely mapping current clone/runtime construction to create_runtime() and _close_storage() to close(), with an integration test against the updated core loader.\n\nThe review also flagged a second major issue: _StorageBundle.release() stops if one helper close() raises, so later helpers can remain open. Close each helper independently while preserving and logging the first exception.


Imported upstream pr-conversation

Final review found one remaining blocker at head 98b259a: repeated runtime.close() is not safely idempotent. A second close can invalidate shared storage, causing a still-live prototype to fail on subsequent database use. The fix needs per-runtime one-shot release semantics plus a regression test that closes the same runtime twice and then exercises the prototype/sibling runtime. A focused repair is underway; all other lifecycle, FD, portability, and test concerns passed.


Imported upstream pr-conversation

Final independent approval review completed at head 95cafc4: no remaining blockers. Verified full pytest (2799 passed, 1 skipped, 12 xfailed), focused lifecycle/core (312 passed), FD hygiene (1 passed), compileall, and diff checks. Verified repeated close is idempotent; prototype and sibling remain usable; bundle refcount and helper close counts are correct; failed-construction cleanup, rebind, concurrency, optional helpers, runtime contract compatibility with hermes-agent PR #79575, portable bootstrap, and bounded FD growth all pass. Ready for maintainer review/merge.

@100yenadmin 100yenadmin added active-continuation Active continuation of an attributed upstream item duplicate This issue or pull request already exists eva-direct Direct impact on Electric Sheep supported Hermes/LCM paths P2 Significant supported-path regression or bounded correctness failure upstream-evidence Preserves links and attribution to the upstream report or pull request upstream-pr Imported upstream pull-request evidence labels Aug 16, 2026
@100yenadmin

Copy link
Copy Markdown
Member Author

Triage: this is one of three open PRs implementing the same architectural change — flagging so it is not reviewed in isolation.

#197, #202 and #215 each introduce a shared, reference-counted SQLite storage bundle across LCM engine clones. All three necessarily relax the same documented guarantee — that a clone owns isolated storage — by removing the six clone._store is not prototype._store / _dag / _lifecycle assertions at tests/test_lcm_core.py:7495 and :7538.

To be clear, that is not test-hiding, and I checked before saying so: all three add replacement assertions for the new invariant (9, 8 and 11 respectively — clone-local session state, one idempotent lease per engine, owner-first shutdown). This is a legitimate contract change with coverage.

The motivation is real and measured, from #197: ten retained clones cost 60 file descriptors and roughly 100 ms of duplicate SQLite helper construction, which risks descriptor exhaustion under parallel child-agent workloads. That is the defect tracked as #9.

So the problem is not any one of these PRs — it is that there are three. Reviewing them independently would mean deciding the same architecture question three times, and merging any one of them makes the other two conflict against a moved contract. The maintainer action is to pick one design, land it, and close the other two with evidence.

This needs an owner/architecture call, because it changes a documented guarantee for every embedder of the engine. It is not a call I will make unilaterally as maintainer. Recorded on #9 as the tracking issue; holding all three until it is decided.

@100yenadmin

Copy link
Copy Markdown
Member Author

Closed superseded by the owner-ratified storage-trio decision: #197 is the pick (memo + ratification on #9, 2026-08-20). Reopenable — this records a product decision, not a merit refutation; if #197's approach hits a wall, this PR's approach is the recorded alternative.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

active-continuation Active continuation of an attributed upstream item duplicate This issue or pull request already exists eva-direct Direct impact on Electric Sheep supported Hermes/LCM paths P2 Significant supported-path regression or bounded correctness failure upstream-evidence Preserves links and attribution to the upstream report or pull request upstream-pr Imported upstream pull-request evidence

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants