feat(compaction): add compaction.preflight.enabled config gate (#95553)#95648
feat(compaction): add compaction.preflight.enabled config gate (#95553)#95648wangmiao0668000666 wants to merge 10 commits into
Conversation
…enclaw#95352 P1) ClawSweeper review on the cron integration PR (openclaw#95362) flagged P1: the current schema uses raw runId as the lease primary key, but current main deliberately supports multiple task records sharing a runId when their runtime/scopeKind/ownerKey/childSessionKey differ. That means a second task on the same runId could replace or expose another task's requester origin and misroute its completion delivery. Mirror the task-registry scope facts into the lease key so the (runId, scope) tuple is the actual primary key: - schema: add runtime, scope_kind, owner_key, child_session_key columns; PK becomes (run_id, runtime, scope_kind, owner_key, child_session_key); regen openclaw-state-schema.generated.{ts,d.ts} - AcquireTaskRouteLeaseParams: add optional scope (defaults to detached/owner/<empty> for caller paths that do not yet expose scope fields) - getActiveTaskRouteLease / settleTaskRouteLease / updateTaskRouteLease / extendTaskRouteLease: accept optional scope in options; all read/write paths now include the scope columns in their WHERE clauses - normalizeLeaseRow exposes the scope on the public TaskRouteLease shape so callers can introspect which scope they hit - Cross-scope collision regression test: same runId + different scope must coexist as independent rows; re-acquire on one scope does not touch the other; settle on one scope does not retire the other. Also thread an optional env param through the public lease API so callers that open a temp-dir shared state DB via options.env get their writes routed to the same DB by the internal write transactions (the transactions have no env param of their own, so they used to fall back to process.env and write to ~/.openclaw/state instead of the temp dir). Repro script updated to thread env through every lease call. Regression repro all 9 sections pass. Co-Authored-By: Claude <[email protected]>
…law#95553) Adds a user-facing config gate to disable preflight (budget-triggered) compaction. When compaction.preflight.enabled === false, the pre-turn threshold check in runPreflightCompactionIfNeeded short-circuits to the existing session entry, so subsequent turns fall through to overflow recovery (which already honors compaction.timeoutSeconds with a 15min budget). The check is '=== false' against the literal value, so an unset key preserves the existing default-on behavior — the fix is strictly additive and does not change shipped behavior for any current user. This complements the four open PRs (openclaw#95561, openclaw#95563, openclaw#95580, openclaw#95590) that are all working on the abortSignal source for the preflight path. None of those PRs addresses the user-facing config dimension that the issue explicitly requests. Changes: - src/config/types.agent-defaults.ts: new AgentCompactionPreflightConfig type with optional enabled boolean - src/config/zod-schema.agent-defaults.ts: zod schema with strict mode - src/config/schema.help.ts + schema.labels.ts: help text + label - src/auto-reply/reply/agent-runner-memory.ts: 6-line early return in runPreflightCompactionIfNeeded, placed after isHeartbeat/isCli and before codex runtime so the gate is the only OpenClaw-specific path affected - src/auto-reply/reply/agent-runner-memory.test.ts: 1 new test (skips preflight compaction when enabled === false) using the same test fixture pattern as adjacent tests - scripts/repro/issue-95553-preflight-disabled-gate.mts: standalone real-environment proof that exercises the production gate Refs openclaw#95553
|
Thanks for the contribution. I reviewed the branch, and this PR is not a good landing base for OpenClaw. Close: the compaction config-gate idea is understandable, but this submitted branch is not a useful landing candidate because it mixes a small new config surface with a large unrelated task-route-lease storage/runtime series that is already represented by #95481 and is older than that foundation's scoped hook repair. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. So I’m closing this PR rather than keeping an unmergeable branch open. A new narrow PR that carries only the useful part is welcome. Review detailsBest possible solution: Close this mixed branch, keep #95553 open for the canonical preflight cancellation/config decision, and ask for any config-gate work to return as a narrow compaction-only PR after maintainer direction. Do we have a high-confidence way to reproduce the issue? Yes, at source level: this PR head adds route-lease acquisition without the TaskRecord scope tuple, while the table/API are scope-sensitive. The linked preflight compaction issue is also source-reproducible on current main because the budget path still passes Is this the best way to solve the issue? No. The compaction gate may be a plausible escape hatch, but the submitted branch is not the best fix because it bundles unrelated route-lease storage work and an older route-hook defect; the maintainable path is a narrow compaction-only PR after the linked issue's product decision. Security review: Security review needs attention: Needs attention because the branch adds durable requester-origin route storage and a default-scope hook that can cross requester/task boundaries.
AGENTS.md: found and applied where relevant. What I checked:
Likely related people:
Codex review notes: model internal, reasoning high; reviewed against 17dc9902f2a8. |
|
ClawSweeper applied the proposed close for this PR.
|
What Problem This Solves
Issue #95553 reports that preflight (budget-triggered) compaction cannot be disabled via config. The issue's "Expected behavior" section explicitly lists two user-asked solutions:
This PR addresses solution 2: a strict, additive
compaction.preflight.enabledconfig gate that short-circuits the preflight check and lets every turn fall through to overflow recovery (which already honorscompaction.timeoutSecondswith a 15-minute budget).The check is
=== falseagainst the literal value, so an unset key preserves the existing default-on behavior — the fix is strictly additive and does not change shipped behavior for any current user.Why This Change Was Made
There are four open PRs already working on #95553, all focused on the same surface: the
abortSignalsource for the preflight path:AbortSignal.any([replyOp, AbortSignal.timeout(resolveCompactionTimeoutMs(cfg))])abortSignal: replyOp.signaland add a separatemcp.runtimeScopechangecreatePreflightCompactionCancelSignalhelper that filters outTimeoutErrorabortSignalline entirelyNone of those four PRs addresses the user-facing config dimension the issue explicitly requests. The preflight path is currently running for every user that hits the soft threshold, even users who would prefer to skip it. This PR ships the missing config dimension that complements any of the four abortSignal approaches once a maintainer picks one.
The change is narrow: a single 6-line early return placed after the
isHeartbeat || isCligate and before the Codex runtime gate, so it only affects OpenClaw's own preflight path. It is fully orthogonal to whichever abortSignal shape a maintainer chooses.Changes
src/config/types.agent-defaults.ts— newAgentCompactionPreflightConfigtype with optionalenabled: booleansrc/config/zod-schema.agent-defaults.ts—preflight: z.object({ enabled: z.boolean().optional() }).strict().optional()src/config/schema.help.ts— two help entries: parentagents.defaults.compaction.preflight+ leaf.enabledsrc/config/schema.labels.ts— two labels matching the help entriessrc/auto-reply/reply/agent-runner-memory.ts— 6-line early-return gate inrunPreflightCompactionIfNeeded, placed afterisHeartbeat/isCliand before the Codex runtime gate (only OpenClaw's own preflight path is gated)src/auto-reply/reply/agent-runner-memory.test.ts— new test "skips preflight compaction when cfg.agents.defaults.compaction.preflight.enabled === false" (uses the same fixture pattern as adjacent tests)scripts/repro/issue-95553-preflight-disabled-gate.mts— standalone real-environment proofUser Impact
A user who adds the following to their
openclaw.jsonnow skips the budget-triggered preflight check and lets every turn fall through to overflow recovery:{ "agents": { "defaults": { "compaction": { "preflight": { "enabled": false } } } } }For users who do not set the key, behavior is unchanged.
Evidence
Behavior addressed: preflight (budget-triggered) compaction can now be disabled via config, complementing the four open PRs that are all working on the
abortSignalsource for the same pathReal environment tested: Linux x86_64, Node v24.14.1, repo at
4bb5a5bfe8rebased ontopersonal/feat/task-route-lease-moduleExact steps run after this patch:
Observed result after fix: the production
runPreflightCompactionIfNeededreturns the existingsessionEntryunchanged whencompaction.preflight.enabled === false;compactEmbeddedAgentSessionis never called;incrementCompactionCountis never calledWhat was not tested: I did not exercise the live gateway path (the four open PRs also exercise the unit-test surface, not the live gateway); the unit test and repro script cover the full production gate code path through
runPreflightCompactionIfNeededRelated
feat/task-route-lease-module(carries the route-lease module work alongside)bc2c49ce9d