Skip to content

feat(compaction): add compaction.preflight.enabled config gate (#95553)#95675

Closed
wangmiao0668000666 wants to merge 3 commits into
openclaw:mainfrom
wangmiao0668000666:fix/95553-preflight-config-gate
Closed

feat(compaction): add compaction.preflight.enabled config gate (#95553)#95675
wangmiao0668000666 wants to merge 3 commits into
openclaw:mainfrom
wangmiao0668000666:fix/95553-preflight-config-gate

Conversation

@wangmiao0668000666

@wangmiao0668000666 wangmiao0668000666 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

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:

  1. Honor agents.defaults.compaction.timeoutSeconds for the preflight/budget path too, or
  2. Add a config toggle agents.defaults.compaction.preflight: false to skip preflight compaction entirely

This PR addresses solution 2: a strict, additive compaction.preflight.enabled config gate that short-circuits the preflight check and lets every turn fall through to overflow recovery (which already honors compaction.timeoutSeconds).

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.

Why This Change Was Made

There are four open PRs already working on #95553, all focused on the same surface: the abortSignal source for the preflight path:

None 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 || isCli gate 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 — new AgentCompactionPreflightConfig type with optional enabled: boolean
  • src/config/zod-schema.agent-defaults.tspreflight: z.object({ enabled: z.boolean().optional() }).strict().optional()
  • src/config/schema.help.ts — two help entries: parent agents.defaults.compaction.preflight + leaf .enabled
  • src/config/schema.labels.ts — two labels matching the help entries
  • src/auto-reply/reply/agent-runner-memory.ts — 6-line early-return gate in runPreflightCompactionIfNeeded, placed after isHeartbeat/isCli and 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)
  • docs/gateway/config-agents.md — add preflight.enabled to the JSON5 example and bullet list under agents.defaults.compaction, matching the schema/help coverage
  • scripts/repro/issue-95553-preflight-disabled-gate.mts — standalone real-environment proof that writes a real openclaw.json and loads it via the production loadConfig() (not a cast)

User Impact

A user who adds the following to their openclaw.json now 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 abortSignal source for the same path

  • Real environment tested: Linux x86_64, Node v24.14.1, repo at 5210d8b121 rebased onto personal/main (base c57fee8239ed)

  • Exact steps run after this patch:

    $ node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-memory.test.ts
    
     RUN  v4.1.7 /home/0668000666/0668000666/AI/OpenClaw/new_open_claw
    
     Test Files  1 passed (1)
          Tests  41 passed (41)
       Start at  15:45:38
       Duration  17.86s (transform 4.48s, setup 395ms, import 8.27s, tests 8.90s, environment 0ms)
    
    [test] passed 1 Vitest shard in 28.18s
    $ node --import tsx scripts/repro/issue-95553-preflight-disabled-gate.mts
    
    === Reproduction for issue #95553 — preflight gate ===
    tmpDir: /tmp/openclaw-95553-repro-XTtBDw
    openclaw.json: /tmp/openclaw-95553-repro-XTtBDw/config/openclaw.json
    sessionFile: /tmp/openclaw-95553-repro-XTtBDw/sessions/session.jsonl
    loaded config: agents.defaults.compaction.preflight.enabled = false
    PASS  preflight.enabled === false short-circuits preflight check
          sessionEntry returned unchanged: session-95553-repro
    === All repro assertions passed ===

    The repro script proves the real openclaw.json → production loadConfig() → production runPreflightCompactionIfNeeded path. It writes openclaw.json to a temp state dir, points OPENCLAW_CONFIG_PATH and OPENCLAW_STATE_DIR at it via withEnvAsync, calls the production loadConfig({ pin: false }), asserts the gate value is parsed from disk, and then exercises the gate on the production preflight function. The function returns the original session entry unchanged; compactEmbeddedAgentSession is never reached.

  • Observed result after fix: the production runPreflightCompactionIfNeeded returns the existing sessionEntry unchanged when compaction.preflight.enabled === false; compactEmbeddedAgentSession is never called; incrementCompactionCount is never called

  • What 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 runPreflightCompactionIfNeeded

ClawSweeper review fixes (commit 5210d8b121)

The 🦪 silver shellfish review flagged three P1 findings on commit a140b0bb1b / ffd17f3a85; all three are addressed in commit 5210d8b121:

  1. [P1] schema.help.ts:1518 timeout wording — replaced hardcoded "15-minute budget" claim with neutral wording that references compaction.timeoutSeconds only (no specific default minutes). The same wording fix applies to the inline code comment in agent-runner-memory.ts. The PR does not need to assume which timeout default the merge target carries.
  2. [P1] public docs coverage — added preflight.enabled to the JSON5 example and the bullet list under agents.defaults.compaction in docs/gateway/config-agents.md. Public docs now describe the new knob consistently with the schema help.
  3. [P1] real OpenClaw setup proof — rewrote the repro script to write a real openclaw.json to a temp state dir and load it through the production loadConfig(). The gate value is now parsed from disk through the same code path the gateway startup uses, not cast from an inline literal.

The single remaining CI failure (checks-node-core-fast, surface budget public exports 10328 > 10327 and public callable exports 5185 > 5184) is pre-existing on openclaw/main HEAD alone — see comment. This PR adds zero new public SDK exports; git diff c57fee8239ed..HEAD -- src/plugin-sdk/ is empty.

Related

…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
@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: M labels Jun 22, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

CI: external blocker on checks-node-core-fast

The checks-node-core-fast failure is pre-existing on openclaw/main and not introduced by this PR.

Reproduction on openclaw/main HEAD 984efdb0b6 alone (without this PR applied):

$ git checkout openclaw/main
$ node scripts/plugin-sdk-surface-report.mjs --check
plugin SDK surface budget failed:
- public exports 10328 > 10327
- public callable exports 5185 > 5184

This PR adds zero new public SDK exports — all seven changed files are config/schema/help/labels/runtime helpers, none touch src/plugin-sdk/**:

$ git diff openclaw/main...HEAD -- src/plugin-sdk/ | wc -l
0

The budget drift (10328 > 10327, 5185 > 5184) was introduced by recent commits on main after the budget bump in commit 77b6ca9a9b fix(sdk): tighten surface report budgets. This is the same class of external CI blocker the maintainers saw on PR #93367code quality > CI status.

What I did fix

The check-lint failure was real and is now fixed in commit ffd17f3a85:

  • scripts/repro/issue-95553-preflight-disabled-gate.mts:60let exitCodeconst exitCode (never reassigned)
  • scripts/repro/issue-95553-preflight-disabled-gate.mts:123 — catch variable typed : unknown

Verified locally:

$ node scripts/run-oxlint.mjs scripts/repro/issue-95553-preflight-disabled-gate.mts
(no output, exit 0)

$ pnpm exec tsx scripts/repro/issue-95553-preflight-disabled-gate.mts
=== Reproduction for issue #95553 — preflight gate ===
PASS  1. preflight.enabled === false short-circuits preflight check
        sessionEntry returned unchanged: session-95553-repro
=== All repro assertions passed ===

$ node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-memory.test.ts
Test Files  1 passed (1) | Tests 41 passed (41)

Re-requesting ClawSweeper review with the lint fix; the surface-budget failure should clear once main rebases past the budget bump.

@clawsweeper

clawsweeper Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Thanks for the contribution. ClawSweeper proposes closing this for now: the implementation may be reasonable, but passing review and proof does not establish that OpenClaw should add this product surface.

Close: the patch is technically narrow and now has focused terminal proof, but it adds a permanent public openclaw.json compaction gate while the canonical compaction issue still needs maintainer product direction on whether to solve this through the existing timeout/cancellation contract, a new config surface, or both.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #95553
Summary: This PR is a candidate implementation for the config-gate half of the canonical preflight compaction timeout issue, while other open PRs target the cancellation/timeout root cause.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

This is a proposal only until the separate default-off apply policy is enabled and all live maintainer-signal checks pass. A maintainer can sponsor the direction, request a narrower version, or apply clawsweeper:human-review to keep it open.

Review details

Best possible solution:

Keep the canonical issue open and land a maintainer-sponsored solution: fix the existing preflight timeout/cancellation contract first, then add an explicit config gate only if maintainers confirm that permanent user-facing surface.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level for the underlying report: current main has no preflight gate and still passes replyOperation.abortSignal into budget preflight compaction. The PR proof exercises the new config parsing and gate path, but not a live slow-backend gateway run.

Is this the best way to solve the issue?

No for unsponsored merge: this is a plausible escape hatch, but not the best confirmed repository direction because the same user problem can be solved by honoring the existing compaction timeout/cancellation contract without adding new config. A maintainer should explicitly sponsor this knob before it becomes public API.

Security review:

Security review cleared: No concrete security or supply-chain concern was found; the diff does not change dependencies, workflows, secrets handling, permissions, or package resolution.

AGENTS.md: found and applied where relevant.

What I checked:

  • PR diff adds a new config gate: The PR adds compaction.preflight.enabled to config schema/types/help/labels/docs and inserts an early return in runPreflightCompactionIfNeeded when the value is exactly false. (src/auto-reply/reply/agent-runner-memory.ts:711, 5210d8b1210d)
  • Current main still lacks the proposed gate: Current main enters non-CLI preflight compaction and passes params.replyOperation.abortSignal into budget compaction; there is no preflight.enabled check on main. (src/auto-reply/reply/agent-runner-memory.ts:981, a6390b2b904d)
  • Existing timeout contract is already centralized: compactWithSafetyTimeout resolves agents.defaults.compaction.timeoutSeconds through resolveCompactionTimeoutMs, so the canonical bug can be addressed without adding a separate user-facing gate if maintainers choose that direction. (src/agents/embedded-agent-runner/compaction-safety-timeout.ts:59, a6390b2b904d)
  • Repository policy raises the bar for new config: Root policy says openclaw.json is already large and new config/env options need proof that existing behavior, defaults, provider selection, or doctor migration cannot solve the need first. (AGENTS.md:67, a6390b2b904d)
  • Config contract alignment was considered: Root policy requires config contract types, schema/help, metadata, baselines, and docs to stay aligned; the PR covers schema/help/labels/docs and CI reports check-docs passing, but product acceptance remains separate. (AGENTS.md:107, a6390b2b904d)
  • Canonical issue is still open and product-scoped: The related issue is still open, explicitly offers either honoring timeoutSeconds or adding a config toggle, and already carries a product-decision signal in the discussion/labels.

Likely related people:

  • vincentkoc: Current local blame attributes the present runPreflightCompactionIfNeeded body to a recent main commit, and GitHub history shows adjacent preflight/compaction maintenance. (role: recent current-source contributor; confidence: medium; commits: a641c0d560fd, 280d1cb977c4, 71fbddd2bb80; files: src/auto-reply/reply/agent-runner-memory.ts, src/agents/embedded-agent-runner/compaction-safety-timeout.ts)
  • Yuval Dinodia: Recent merged commits changed stale-token and projected-token behavior in the same preflight compaction gate being modified here. (role: recent preflight compaction contributor; confidence: high; commits: bc4b1b018a3e, caab3434612c; files: src/auto-reply/reply/agent-runner-memory.ts)
  • ArthurNie: The hard required-preflight behavior for oversized agent turns appears in commit 9d54285b0d4a, directly adjacent to the behavior this PR gates. (role: preflight hard-gate contributor; confidence: high; commits: 9d54285b0d4a; files: src/auto-reply/reply/agent-runner-memory.ts)
  • wangmiao0668000666: Beyond authoring this PR, prior merged history shows work on the compaction timeout default and docs, which is central to the alternative fix direction. (role: timeout contract contributor; confidence: high; commits: bb6e47729cf8, 5210d8b1210d; files: src/agents/embedded-agent-runner/compaction-safety-timeout.ts, docs/gateway/config-agents.md, src/config/schema.help.ts)
  • Peter Steinberger: History for the timeout wrapper and config documentation shows repeated adjacent work on compaction safety, config docs, and runtime internals. (role: adjacent compaction/config contributor; confidence: medium; commits: bf3921dab762, 43190f5248b5; files: src/agents/embedded-agent-runner/compaction-safety-timeout.ts, src/config/schema.help.ts, docs/gateway/config-agents.md)

Codex review notes: model internal, reasoning high; reviewed against a6390b2b904d.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 22, 2026
…al-setup repro (openclaw#95553)

Address ClawSweeper P1 findings on PR openclaw#95675:
- schema.help.ts:1518 - replace hardcoded '15-minute budget' wording with
  neutral description that references timeoutSeconds only (no specific
  default minutes). Keeps wording correct regardless of which default
  the merge target carries.
- agent-runner-memory.ts comment - same neutral wording fix.
- docs/gateway/config-agents.md - add preflight.enabled to the JSON5
  example and bullet list under agents.defaults.compaction, matching
  the schema/help coverage.
- scripts/repro/issue-95553-preflight-disabled-gate.mts - rewrite the
  repro to write a real openclaw.json to a temp dir and load it through
  the production loadConfig() so the gate value is parsed from disk,
  not cast from an inline literal. Same production path the gateway
  startup uses.
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation gateway Gateway runtime triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jun 22, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

P1 findings on the previous review (commit a140b0b / ffd17f3) are all addressed in commit 5210d8b (just pushed):

  1. schema.help.ts:1518 — replaced hardcoded '15-minute budget' wording with neutral phrasing that references timeoutSeconds only. Same fix in agent-runner-memory.ts code comment.
  2. public docs — added preflight.enabled to the JSON5 example and bullet list under agents.defaults.compaction in docs/gateway/config-agents.md.
  3. real-setup proof — rewrote the repro script to write a real openclaw.json to a temp state dir and load it through the production loadConfig() (withEnvAsync OPENCLAW_CONFIG_PATH / OPENCLAW_STATE_DIR). The gate value is now parsed from disk through the same code path the gateway startup uses, not cast from an inline literal.

Real-environment test (just run):
$ node --import tsx scripts/repro/issue-95553-preflight-disabled-gate.mts
=== Reproduction for issue #95553 — preflight gate ===
tmpDir: /tmp/openclaw-95553-repro-XTtBDw
openclaw.json: /tmp/openclaw-95553-repro-XTtBDw/config/openclaw.json
sessionFile: /tmp/openclaw-95553-repro-XTtBDw/sessions/session.jsonl
loaded config: agents.defaults.compaction.preflight.enabled = false
PASS preflight.enabled === false short-circuits preflight check
sessionEntry returned unchanged: session-95553-repro
=== All repro assertions passed ===

Vitest unit test:
$ node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-memory.test.ts
Test Files 1 passed (1)
Tests 41 passed (41)

PR body updated with the new evidence section + review fixes section.

@clawsweeper

clawsweeper Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 22, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Nudge: the previous re-review on commit 5210d8b was acknowledged but the verdict comment has not been emitted yet (PR still carries the original a140b0b verdict). All P1/P2/P3 findings on the original review are addressed in commit 5210d8b:

  1. P1 (help text 15-minute wording) — neutralized to reference timeoutSeconds only.
  2. P1 (real OpenClaw setup proof) — repro rewritten to write a real openclaw.json and load it through production loadConfig().
  3. P1 (public docs) — docs/gateway/config-agents.md JSON5 example + bullet list updated.
  4. P2/P3 — covered by the same fixes.

PR body has been refreshed with the new evidence section + a findings reconciliation table.

Real-environment output from the new repro:

$ node --import tsx scripts/repro/issue-95553-preflight-disabled-gate.mts
=== Reproduction for issue #95553 — preflight gate ===
tmpDir: /tmp/openclaw-95553-repro-XTtBDw
openclaw.json: /tmp/openclaw-95553-repro-XTtBDw/config/openclaw.json
sessionFile: /tmp/openclaw-95553-repro-XTtBDw/sessions/session.jsonl
loaded config: agents.defaults.compaction.preflight.enabled = false
PASS preflight.enabled === false short-circuits preflight check
sessionEntry returned unchanged: session-95553-repro
=== All repro assertions passed ===

Vitest:
$ node scripts/run-vitest.mjs src/auto-reply/reply/agent-runner-memory.test.ts
Test Files 1 passed (1)
Tests 41 passed (41)

Remaining checks-node-core-fast failure is pre-existing on openclaw/main at PR base a0ab5c0 (surface budget 10328 > 10327 / 5185 > 5184 reproduces without my PR).

@clawsweeper clawsweeper Bot added status: 🔁 re-review loop A fresh ClawSweeper review was explicitly requested after the latest review. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 🔁 re-review loop A fresh ClawSweeper review was explicitly requested after the latest review. labels Jun 22, 2026
@wangmiao0668000666

Copy link
Copy Markdown
Contributor Author

Closing after analysis per @wangmiao0668000666's review.

Why close:

  1. Product-decision blocker — issue Bug: preflight (budget-triggered) compaction hard-capped at ~60s, ignores compaction.timeoutSeconds #95553 carries clawsweeper:needs-product-decision; maintainers haven't chosen between the two approaches in the issue body. Code quality can't solve this.
  2. fix(reply): let preflight compaction use compaction timeout #95590 (yu-xin-c, 🐚 ready for maintainer look) is the simpler fix: drop the abortSignal line from runPreflightCompactionIfNeeded. Same rating, narrower surface, no permanent config contract.
  3. This PR's config-gate approach (preflight.enabled) would be a permanent openclaw.json surface that may not be needed once the root-cause abort-signal fix lands.

Preserved in branch fix/95553-preflight-config-gate if maintainers decide they want the config dimension later.

Refs #95553

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

Labels

docs Improvements or additions to documentation gateway Gateway runtime merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant