perf(agent): bound and coalesce SWM expiry cleanup - #2518
branarakic wants to merge 76 commits into
Conversation
…1961-bounded-swm-expiry
|
Updated this PR with current testnet-canary in 736104d after CI run34356103537 failed the selected-private durable catalog restart integration. The branch now includes the already-landed catalog replay and empty identity-response retry fixes (#2521/#2508). The exact failing restart case passes locally, as do 198 cleanup/responder/shutdown tests and all five additional TTL cases on this merged head. Dependency/agent builds, public/fixture types, lint, 1797-file inventory and SPARQL checks pass. Fresh CI is running. |
otReviewAgent
left a comment
There was a problem hiding this comment.
Operational Notice: Review Agent could not complete this review.
Business logic reviewer failed: Selected model is at capacity. Please try a different model.
otReviewAgent
left a comment
There was a problem hiding this comment.
Operational Notice: Review Agent could not complete this review.
Business logic reviewer failed: retry_exhausted
Review asked that the connector strategy own the full lifecycle or be removed, because extracting only the connect phase left the other phases as hard-coded connector checks in two already busy modules and created several authoritative places for connector behaviour. Teardown and cancellation had already moved behind the strategy; refresh had not. `refreshLocalAgentIntegrationFromUi` was an if/else cascade over 'prime-agent', 'hermes', 'openclaw' and a bare fallback. Each branch body moves 1:1 onto its connector as `createRefreshPlan`, the generic connector keeps the empty-patch fallback, and the orchestrator collapses to resolving the integration and dispatching through `localAgentConnectorFor`. Probe behaviour, notices, metadata pinning and the OpenClaw bridge-health reset are unchanged, and refresh still exposes no injection point, so the arity guard that pins "Refresh never runs setup" keeps holding. `createRefreshPlan` is required on the contract, so a connector that implements only part of the lifecycle no longer compiles. A type test asserts that, and a routes test drives connect, refresh, cancellation and disconnect for every registered connector plus an unregistered id through the one contract. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
otReviewAgent
left a comment
There was a problem hiding this comment.
Operational Notice: Review Agent could not complete this review.
Business logic reviewer failed: retry_exhausted
otReviewAgent
left a comment
There was a problem hiding this comment.
Operational Notice: Review Agent could not complete this review.
Business logic reviewer failed: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Sep 20th, 2026 9:00 AM.
|
I reran the failed jobs from the previous CI attempt after reproducing the cleanup path locally. The affected SWM expiry suites pass 55/55 locally, including bounded batches, single-flight cleanup, fairness, publisher locking, external-store draining, and TTL behavior. The rerun is in progress; no code change was needed for the prior timing-sensitive failures. |
|
The rerun of |
|
CI follow-up pushed at |
otReviewAgent
left a comment
There was a problem hiding this comment.
Operational Notice: Review Agent could not complete this review.
Business logic reviewer failed: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Sep 20th, 2026 9:00 AM.
|
CI follow-up: the red agent shard reproduced the storage-scan abort assertion on rerun. The test used a 1 ms budget and 20 ms delay, which can resolve in the wrong order under the sharded runner. It now uses a 50 ms budget with a 250 ms delayed scan, preserving the abort assertion while removing the timing race. Validation: focused |
otReviewAgent
left a comment
There was a problem hiding this comment.
Operational Notice: Review Agent could not complete this review.
Business logic reviewer failed: You've hit your usage limit. Visit https://chatgpt.com/codex/settings/usage to purchase more credits or try again at Sep 20th, 2026 9:00 AM.
SWM expiry cleanup processes at most 250 operations per page and four nonempty pages per physical pass. Continuations visit remaining targets fairly and stop when no operations are removed. Manual cleanup awaits the drain; periodic maintenance yields between bounded passes. Each pass uses one explicit cutoff, and retention changes invalidate active generations.
Cleanup and publisher writes share entity/KA lock identities. Operations are revalidated under those locks before deletion, and newer KA heads survive expiry of old operations. Storage resolves complete graph families, preserving staging data and root/subgraph identities. Four concurrent operation pipelines drain every admitted sibling; counted mutations remain serialized per target. A targeted post-delete metadata check drives progress, so unrelated writes that offset graph-wide deletion counts cannot strand later expired pages.
TTL, LLM and telemetry settings use one live DkgConfigStore per resolved file. The generic ConfigFileStore owns only atomic publication and serialization. Opening the live owner drains previously admitted local writes, acquires a process-wide SQLite file lock, and loads the initial deeply immutable snapshot while holding that lock. Standalone configuration writes use the same lock; a CLI such as publisher enable is explicitly rejected while the daemon owns the file. The permanent empty sidecar carries no configuration data, and the operating system releases ownership after normal closure or process death. A completed pre-claim save is authoritative as a full snapshot, so deleted optional fields cannot be restored from stale startup state. Direct paths, file symlinks and directory aliases share that owner.
Each live update rebases inside the publication queue and explicitly declares either configuration-only semantics or a prepared runtime apply/rollback pair. The file candidate publishes before activation. Failed publication leaves runtime untouched; failed activation invokes compensation and restores the exact prior file before admitting another update. Both recovery steps are attempted independently, with aggregated errors and a retained backup if file restoration fails. If either recovery step fails, the live owner rejects queued and later updates before candidate preparation and retains its write claim until closure; settings changes require a daemon restart. Ordinary activation failures with successful recovery keep the lane usable. TTL compensation restores retention, LLM compensation restores the memory manager, and telemetry compensation restores the previous gate and signals.
Slow local-agent connect and refresh preparation remains outside the commit queue. Producers return explicit attach-state patches alongside response records; connect also returns normalized registration intent and carries failed-probe state in a typed error. Routes rebase that intent and those patches through the live owner, preserving concurrent operator metadata/capability edits, applying the probe result even when it matches the starting snapshot, and honoring newer operator disconnects. Deferred attach completion uses the same explicit patch contract. Read helpers accept immutable inputs; mutations use explicit drafts and owner updates. Daemon startup uses an explicitly immutable startupConfig; telemetry callbacks read the current committed settings at each activation while resource identity remains tied to startup. Request contexts expose the canonical store directly, and Kafka reads its namespaced settings from that live readonly projection on each dispatch. The create and subscribe --save CLI flows persist always-on subscriptions through the existing daemon subscription owner instead of writing a second config snapshot.
Validation:
Closes #1961.