You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by "Joob1n (via GitHub)" <gi...@apache.org> on 2026/09/03 14:16:54 UTC

[PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Joob1n opened a new pull request, #4667:
URL: https://github.com/apache/maka/pull/4667

   ## Summary
   
   PR 2 of the series on #4559, following the merged #4653. It is the compaction module's failure path and nothing else: 4 files, no protocol change.
   
   When the summarizer's own provider rejects a fold as too large, the planner halved the covered range and tried again. Halving is a guess in both directions. It can overshoot, discarding verbatim history the summarizer would have accepted, and it can undershoot, paying another provider round trip to find that out. The loop then exited through span selection, so the diagnostic reported a span problem for what was a provider verdict.
   
   There is a boundary that needs no guessing. **The last accepted request's input covered everything before the newest model reply began.** That span was accepted by this model on this connection, so it is provably within the provider's capacity. The fold retreats to it once; a rejection of that span too is the provider saying this fold cannot be made, and the fold fails open with the summarizer's own reason.
   
   ```
   fold the largest safe prefix
     -> rejected as too large
          -> retreat to the span the last accepted input covered
               -> rejected again  -> fail open, the provider decides
               -> accepted        -> checkpoint
     -> no model reply on the ledger -> no proven boundary -> fail open, no retry
   ```
   
   The boundary is read from the ledger rather than persisted, so there is no schema or epoch change. The newest model reply ends the proven span whether or not it sits at the tail: at a turn's first request the newest events are the user's message and its tool results, and the span still ends where the previous turn's reply began.
   
   Refs #4559, #4634
   
   ## Not in this PR
   
   The last reply's own span is still kept verbatim when the retreat happens. Folding it separately above a watermark (24,000 tokens) is the remaining half of the compaction module and follows next, along with "compact and retry" for an unrecognised rejection (#4623).
   
   ## Verification
   
   Every local gate clean. Runtime suites: history compaction 21/21, overflow recovery 50/50, mid-turn capacity 73/73, checkpoint and summarizer suites unchanged and green. `runtime-host` protocol and composition 28/28 (that suite times out under parallel load on my machine and passes on its own; CI runs it serially). The epoch guard confirms no protocol change against the base.
   
   ## Self-review
   
   - The first implementation read `refs.stepId` to find the newest reply. Tests showed that field is only set on function-call events, so a plain text reply left no boundary and the retreat would have silently never fired — worse than halving. The role-based rule replaced it.
   - The second implementation looked only at the ledger tail, which is correct mid-turn but wrong at a turn's first request, where the tail is the new user message. Scanning for the newest reply anywhere fixes that case, and the step-0 recovery test covers it.
   - `step-0 overflow recovery gates reasoning on retry and durable reload` previously relied on two halving retreats to keep the reasoning tail out of the fold. It now rejects once and the proven boundary leaves that tail verbatim, so the reasoning-gating assertions it exists for are unchanged.
   
   ## AI use
   
   Select exactly one:
   
   - [ ] No generative tool made a substantive contribution
   - [x] Generative tooling made a substantive contribution
   
   Tool(s) and scope: Claude Code — implementation; reviewed and verified by the author.
   
   ## Checklist
   
   - [x] Tests cover the change and fail without it
   - [x] Lint, format, typecheck and the affected suites pass locally
   
   Does this PR entail a change in behavior?
   
   - [x] Yes — described under Summary above
   - [ ] No
   
   https://claude.ai/code/session_014ajaRxC4jydavY9nYUFj5J
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


Re: [PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Posted by "Astro-Han (via GitHub)" <gi...@apache.org>.
Astro-Han commented on PR #4667:
URL: https://github.com/apache/maka/pull/4667#issuecomment-5528781266

   Severities for the comment above, which I should have included with it.
   
   **P1 — the standalone retreat is unwired.** Normal supported operation: any `/compact`, supervisor-wake sub-agent compaction, or pre-turn fallback whose summarizer request the provider rejects as too large, which is the ordinary long-session case since the first attempt covers the whole prior session. `ai-sdk-compaction.ts:365` passes neither `runHeaders` nor `acceptedRoute`, so `acceptedInputBoundary` returns `undefined` and the first rejection fails open, where halving previously walked down until a span was accepted. The first three entries report failed with a `context_compaction_failed_open` note; `ai-sdk-backend.ts:3426` sends the oversized history and the turn dies with `context_overflow`. No flag or fallback. The fix is the two lines already at `:1072`.
   
   **P2 — the new planner tests prove no production obligation.** They pair `phase: 'standalone'` with a hand-supplied `acceptedRoute`, a combination neither call site produces, so they would stay green with both call sites deleted. One case driving `AiSdkCompaction.compactHistory` closes it.
   
   **P2 — `CHANGELOG.md:51` describes behavior the shipped code does not have** on `/compact`, supervisor-wake compaction and the pre-turn fallback. Land the wiring rather than reword the line.
   
   **P3 — mid-turn cannot reach a retreat either**, since `priorRunHeaders` excludes the current turn so the proven index lands at or below `headAnchorIndex` while the gate wants above it. Pre-existing: the gate is unchanged and halving usually undershot it too. A follow-up, not a fix under time pressure.
   
   **No finding** on the `overflow-reactive-recovery.test.ts` edit, on route collision, on reply-role coverage, on idempotence, or on the interaction with #4653 and #4669.
   
   The P1 is the one worth a decision before the cut: land the two lines, or revert this for the release.
   
   <details><summary>简体中文</summary>
   
   上面那条评论的分级,应该跟着一起给的。
   
   **P1 —— standalone 的退避没接线。** 正常支持路径:任何 `/compact`、supervisor-wake 的 sub-agent 压缩、或 pre-turn 兜底,只要 summarizer 请求被 provider 判为过大就会撞上,而第一次尝试覆盖整个既往会话,所以这就是长会话的常规情况。`ai-sdk-compaction.ts:365` 既没传 `runHeaders` 也没传 `acceptedRoute`,`acceptedInputBoundary` 返回 `undefined`,第一次被拒就 fail open,而折半原本会一路走到某个跨度被接受。前三个入口报失败并写一条 `context_compaction_failed_open`;`ai-sdk-backend.ts:3426` 会把超窗历史发出去,turn 死在 `context_overflow`。没有开关也没有兜底。修法是 `:1072` 已有的那两行。
   
   **P2 —— 新加的 planner 测试没有证明任何生产义务。** 它们把 `phase: 'standalone'` 和手工塞的 `acceptedRoute` 配在一起,而两个调用点都不会产生这个组合,所以把两个调用点都删掉它们照样绿。补一条驱动 `AiSdkCompaction.compactHistory` 的用例即可。
   
   **P2 —— `CHANGELOG.md:51` 描述的行为在 `/compact`、supervisor-wake 压缩和 pre-turn 兜底上并不存在。** 应该补接线,而不是改措辞。
   
   **P3 —— mid-turn 同样到不了退避**,因为 `priorRunHeaders` 排除了当前 turn,proven 下标必然落在 `headAnchorIndex` 或之前,而闸要求在它之上。既有问题:闸没变,折半通常也过不去。跟进即可,不必在赶时间的时候动。
   
   **无发现**:`overflow-reactive-recovery.test.ts` 的改动、route 碰撞、reply 角色覆盖、幂等性,以及与 #4653、#4669 的交互。
   
   发版前需要拍板的只有那条 P1:补上两行,或者这次先 revert。
   
   </details>
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


Re: [PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Posted by "likun666661 (via GitHub)" <gi...@apache.org>.
likun666661 merged PR #4667:
URL: https://github.com/apache/maka/pull/4667


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


Re: [PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Posted by "Joob1n (via GitHub)" <gi...@apache.org>.
Joob1n commented on PR #4667:
URL: https://github.com/apache/maka/pull/4667#issuecomment-5528664061

   Confirmed, and it is a regression this PR introduced rather than a gap it left: the standalone site retreated before, because its coverage gate admitted every halving step. Fixed in #4671, with the two values that were already in hand there.
   
   Your point about the test is the one that matters most: the planner tests hand `acceptedRoute` in directly, so they would have stayed green with both call sites deleted. #4671's test drives `compactHistory` and asserts both attempts, and it fails without the wiring.
   
   I also confirmed the mid-turn observation. `priorRunHeaders` excludes the current turn, so the proven index lands at or below `headAnchorIndex` while the gate wants it above, and mid-turn cannot reach a retreat today. As you say, halving usually undershot the same gate, so it is a pre-existing limit rather than something this PR changed; it needs its own change to the gate and is not in #4671.
   
   Thank you for tracing the four entry points and for saying which parts you had checked and which were a static read.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


Re: [PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Posted by "Astro-Han (via GitHub)" <gi...@apache.org>.
Astro-Han commented on code in PR #4667:
URL: https://github.com/apache/maka/pull/4667#discussion_r3926558106


##########
packages/runtime/src/ai-sdk-compaction.ts:
##########
@@ -1069,6 +1069,11 @@ export class AiSdkCompaction {
       phase: input.phase ?? 'mid_turn',
       orderedEvents,
       headAnchor: { runtimeEventId: state.headAnchor.id, turnId },
+      runHeaders: state.priorRunHeaders,
+      acceptedRoute: {

Review Comment:
   **P1** These two lines are the whole wiring, and they only reach the mid-turn and pre-turn call site. The sibling call at `:365` (`phase: 'standalone'`) passes neither, so `acceptedInputBoundary` returns `undefined` on its first line and the first `input_too_large` fails open there, where halving previously walked down until a span was accepted (that path's coverage gate is just `coveredCount > 0`, so every halving step passed it).
   
   Four entries reach it: CLI `/compact`, Desktop `sessions:compact`, supervisor-wake sub-agent compaction (`agent-graph-supervisor-wake.ts:111`), and the pre-turn fallback at `ai-sdk-backend.ts:3426`. The first three end failed with a `context_compaction_failed_open` note; the fourth sends the oversized history and the turn dies with `context_overflow`. No flag or fallback. And the standalone first attempt covers the entire prior session (`reserveTailEvents: 0`), the span most likely to be rejected, so it is the ordinary long-session case.
   
   Both values are in hand at `:365`, where `input.runtimeContextRunHeaders` is already used ten lines below:
   
   ```ts
   ...(input.runtimeContextRunHeaders ? { runHeaders: input.runtimeContextRunHeaders } : {}),
   acceptedRoute: {
     modelId: this.input.modelId,
     ...(this.targetConnectionId !== undefined ? { connectionId: this.targetConnectionId } : {}),
   },
   ```
   
   **P3, separately**: `state.priorRunHeaders` excludes the current turn by construction (`prior-run-context.ts:66-71` filters `run.turnId !== currentTurnId`), so no current-turn reply can be on route and the proven index always lands at or below `headAnchorIndex`, while the `mid_turn` gate wants strictly above it. So mid-turn cannot reach a retreat either. That gate is unchanged from before and halving usually undershot it too, so this is a pre-existing limit rather than something this PR broke. A follow-up, not a fix under time pressure. If you do pursue it, the current run is the route by construction, so a synthetic header for `input.origin.runId` or a `currentRunId` field treated as on-route would make the comment at `history-compaction.ts:239-246` true.



##########
packages/runtime/src/history-compaction.ts:
##########
@@ -282,11 +326,28 @@ export async function planHistoryCompaction(
       if (error instanceof HistoryCompactSummarizerError) {
         if (error.reason === 'input_too_large') {
           // The summarizer's provider said this span does not fit its own
-          // window; that is the only fit signal the fold listens to. Retreat by
-          // half rather than by one event: each retreat is a real provider
-          // round trip, and the loop exits through no_safe_completed_span when
-          // even the smallest legal span is refused.
-          maxCoveredCount = Math.floor(boundary.coveredCount / 2);
+          // window; that is the only fit signal the fold listens to. Retreat to
+          // the span the last accepted request's input covered: that span was
+          // accepted by this model on this connection, so it is provably within
+          // capacity, where halving the range is a guess that can overshoot
+          // (throwing away verbatim history for nothing) or undershoot (paying
+          // another round trip). Only one retreat is available, because there
+          // is only one proven boundary; a rejection of that span too is the
+          // provider saying this fold cannot be made, and the fold fails open
+          // (#4559).
+          const proven = acceptedInputBoundary(
+            input.orderedEvents,
+            input.runHeaders ?? [],
+            input.acceptedRoute,
+          );
+          if (proven === undefined || proven >= boundary.coveredCount) {

Review Comment:
   **Context for the P1 above.** This early exit is correct and it does report the summarizer's own reason, which was the point. It is just reached unconditionally on the standalone path, because `acceptedInputBoundary` returns `undefined` whenever `acceptedRoute` is absent and `:365` never passes one.



##########
packages/runtime/src/__tests__/history-compaction.test.ts:
##########
@@ -203,24 +209,195 @@ describe('plan context compaction', () => {
     if (result.decision !== 'compacted') return;
     assert.deepEqual(attemptedCoverage, [
       ['old-user', 'old-model', 'recent-user', 'recent-model'],
-      ['old-user', 'old-model'],
-      ['old-user'],
+      ['old-user', 'old-model', 'recent-user'],
     ]);
     assert.deepEqual(
       result.tailRuntimeEvents.map((event) => event.id),
-      ['old-model', 'recent-user', 'recent-model'],
+      ['recent-model'],
+    );
+  });
+
+  test('a later fold rolls over the reply the retreat left verbatim', async () => {
+    // The retreat keeps the newest reply out of the fold, so it stays in the
+    // request as raw text. It does not stay there: the next fold covers it,
+    // rolling the checkpoint forward, because by then a newer reply ends the
+    // proven span. This bounds how long a retreat's leftover survives.
+    const first = [
+      user('old-user', 'old-turn'),
+      model('old-model', 'old-turn', 'old result'),
+      user('recent-user', 'recent-turn'),
+      model('recent-model', 'recent-turn', 'recent result'),
+    ];
+    let attempts = 0;
+    const retreated = await planHistoryCompaction(
+      planInput({
+        phase: 'standalone',

Review Comment:
   **P2** These cases pair `phase: 'standalone'` with a hand-supplied `acceptedRoute`, and no production caller produces that combination: the standalone site passes neither field, and the site that passes them is mid-turn or pre-turn. So they prove the boundary arithmetic but not one production obligation, and they would stay green if both call sites were deleted. That is what let the wiring gap through.
   
   One case driving `AiSdkCompaction.compactHistory` rather than `planHistoryCompaction` directly, asserting a second summarizer call after one `input_too_large`, closes it. The `overflow-reactive-recovery.test.ts` assertion is the only production-wired one today, and it covers the one phase where the wiring happens to work.



##########
CHANGELOG.md:
##########
@@ -48,6 +48,7 @@
   owner, immutable request snapshots remain enforced at AgentRun acceptance and backend dispatch,
   and SessionEvent-to-RuntimeEvent conversion remains a pure mapper.
 - Retired the Task Ledger domain: SessionTodo is now the sole authority for in-session work items, and the operational-state schema drops the `workflow_task_ledger_events` table on first open. **Unfinished Tasks are not migrated and are permanently deleted.** This affects workspaces last opened by `v0.1.0` through `v0.1.11`, `cli-v0.1.0-beta.1`, `v0.2.0-incubating-rc1`, or a `v0.2.0-dev` build; those releases wrote Tasks to a table that no shipped build ever bridged into SessionTodo. Before opening such a workspace with this build, finish or export the Tasks you still need, or copy the workspace's `runtime.sqlite` aside — the migration removes the only live copy, so afterwards recovery requires a backup made in advance.
+- A compaction rejected as too large for the summarizer's own window now retreats to the span the last accepted request's input covered, instead of halving the covered range. That span is the newest reply this route produced, found through the run headers, so it was accepted by this model on this connection and is provably within capacity; halving can overshoot (discarding verbatim history for nothing) or undershoot (paying another round trip), and a span another route accepted proves nothing at all. One retreat, then the fold fails open and the provider decides.

Review Comment:
   **P2** This is true for step-0 recovery and not for `/compact`, supervisor-wake compaction, or the pre-turn fallback, where there are zero retreats. Land the wiring rather than rewording the line, since rewording would document the gap.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


Re: [PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Posted by "Joob1n (via GitHub)" <gi...@apache.org>.
Joob1n commented on PR #4667:
URL: https://github.com/apache/maka/pull/4667#issuecomment-5527982514

   You are right, and the claim in the code comment was stronger than what the code proved. Fixed on `378f987f1`.
   
   `acceptedInputBoundary` now finds the newest reply produced **on the route this fold is dispatched on**, resolving each candidate reply's `runId` through the run headers and matching `modelId` and `llmConnectionId` — the same pairing `persistedRequestAnchor` enforces. The caller passes `runHeaders` and `acceptedRoute`; a role-only scan was the bug, because a session's history can span runs on several routes and a span another model accepted says nothing about this summarizer's window.
   
   Two regressions:
   
   - "a mixed-route session retreats to this route's own newest reply" — four events where the newest reply belongs to `model-b`/`conn-b` and an older one to the active `model-a`/`conn-a`. The retreat targets the older boundary, not the nearer foreign one; the assertion spells out the wrong answer it would otherwise give.
   - "fails open when only another route has ever been accepted" — one attempt, no retreat, fail open. Nothing proven means no retreat, which is the same rule as before, now correctly scoped.
   
   Still no schema or epoch change: the boundary is read from the ledger and its run headers.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org


Re: [PR] fix(runtime): retreat a rejected fold to a span the provider has accepted [maka]

Posted by "Astro-Han (via GitHub)" <gi...@apache.org>.
Astro-Han commented on PR #4667:
URL: https://github.com/apache/maka/pull/4667#issuecomment-5528563327

   Nice change, and the proven boundary is a much better idea than halving. One thing after the merge, only because a release is close: the retreat is wired into one of the two production call sites, and the one it misses is the one `/compact` uses.
   
   The five added lines land at `ai-sdk-compaction.ts:1072` (mid-turn and pre-turn). The standalone site at `ai-sdk-compaction.ts:365` passes neither `runHeaders` nor `acceptedRoute`, so `acceptedInputBoundary` returns `undefined` on its first line and the first `input_too_large` fails open right away.
   
   That path did retreat before. Its coverage gate is just `coveredCount > 0`, so every halving step passed it and the loop walked down until a span was accepted. The test you rewrote, `retreats the safe prefix by half for each input-too-large rejection`, was itself `phase: 'standalone'`.
   
   Four entries reach it: CLI `/compact`, Desktop `sessions:compact`, supervisor-wake sub-agent compaction (`agent-graph-supervisor-wake.ts:111`), and the pre-turn fallback at `ai-sdk-backend.ts:3426`. The first three end as failed with a `context_compaction_failed_open` note; the fourth sends the oversized history and the turn dies with `context_overflow`. And the standalone first attempt covers the whole prior session (`reserveTailEvents: 0`), which is the span most likely to be rejected, so it is the ordinary long-session case.
   
   The fix is the two lines already at `:1072`, and both values are in hand there (`input.runtimeContextRunHeaders` is used ten lines below):
   
   ```ts
   ...(input.runtimeContextRunHeaders ? { runHeaders: input.runtimeContextRunHeaders } : {}),
   acceptedRoute: {
     modelId: this.input.modelId,
     ...(this.targetConnectionId !== undefined ? { connectionId: this.targetConnectionId } : {}),
   },
   ```
   
   Worth one test driving `AiSdkCompaction.compactHistory` rather than `planHistoryCompaction` directly. That is the gap that let it through: the new planner tests use `phase: 'standalone'` with a hand-supplied `acceptedRoute`, which neither call site produces, so they would stay green if both call sites were deleted.
   
   Two things I checked and they are fine. The `overflow-reactive-recovery.test.ts` edit is clean: only the two call counts moved, every assertion carrying the obligation is unchanged, and it still exercises one real retreat. And mid-turn cannot reach a retreat either, since `priorRunHeaders` excludes the current turn so the proven index lands at or below `headAnchorIndex` while the gate wants above it. But that gate is unchanged and halving usually undershot it too, so it is a pre-existing limit, not something you broke. A follow-up, not a fix under time pressure.
   
   Static read of `a45346ca` against `b9748a77`, no tests run, so the standalone claim is a trace rather than an observation. One test call against `compactHistory` settles it in a minute.
   
   AI-assisted review: drafted with Maka. I verified the call sites, the gates and the entry points myself.
   
   <details><summary>简体中文</summary>
   
   改得挺好,用被证明过的边界替代折半是更对的思路。合并之后才提一句,只因为发版临近:退避接到了两个生产调用点里的一个,而漏掉的那个正是 `/compact` 走的。
   
   加的五行落在 `ai-sdk-compaction.ts:1072`(mid-turn 和 pre-turn)。`ai-sdk-compaction.ts:365` 的 standalone 调用点 `runHeaders` 和 `acceptedRoute` 都没传,于是 `acceptedInputBoundary` 第一行就返回 `undefined`,第一次 `input_too_large` 直接 fail open。
   
   这条路改动前是有退避的。它的覆盖闸只是 `coveredCount > 0`,折半到哪一步都能过,循环会一路走到某个跨度被接受。你改写掉的那条 `retreats the safe prefix by half for each input-too-large rejection` 本身就是 `phase: 'standalone'`。
   
   四个入口会走到:CLI `/compact`、Desktop `sessions:compact`、`agent-graph-supervisor-wake.ts:111` 的 sub-agent 自动压缩,以及 `ai-sdk-backend.ts:3426` 的 pre-turn 兜底。前三个以失败收场并写一条 `context_compaction_failed_open`;第四个会把超窗历史发出去,turn 死在 `context_overflow`。而 standalone 的第一次尝试覆盖整个既往会话(`reserveTailEvents: 0`),正是最容易被拒的那个跨度,所以这是长会话的常规情况。
   
   修法就是 `:1072` 已有的那两行,两个值在这个点都是现成的(`input.runtimeContextRunHeaders` 在下面十行就在用)。
   
   建议补一条驱动 `AiSdkCompaction.compactHistory` 而不是直接调 `planHistoryCompaction` 的测试。这正是它溜过去的缺口:新加的 planner 测试是 `phase: 'standalone'` 配手工塞的 `acceptedRoute`,两个调用点都不会产生这个组合,所以把两个调用点都删掉它们照样绿。
   
   两件我核过、没问题的事。`overflow-reactive-recovery.test.ts` 的改动是干净的:只动了两个调用计数,承载义务的断言一条没变,而且仍然跑了一次真实退避。另外 mid-turn 其实也到不了退避,因为 `priorRunHeaders` 排除了当前 turn,proven 下标必然落在 `headAnchorIndex` 或之前,而闸要求在它之上;但这个闸和改动前一样,折半通常也过不去,所以是既有限制,不是你弄坏的。跟进即可,不必在赶时间的时候动。
   
   </details>
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org