fix(coding-agent): port no-preparation dead-end rescue to the tiered #rescueCompactionDeadEnd API
Main renamed/refactored #tryShakeRescueForDeadEnd + #emitShakeRescueNotice into the tiered #rescueCompactionDeadEnd (elide, then image drop, notices emitted internally), so a textually-clean merge of this branch left calls to undefined private methods. Re-express the !preparation rescue through the new API: progress = prepareCompaction succeeding on the rewritten branch, skipElide when falling through from a shake pass (the image tier still gets a chance), and historyRewritten flagged whenever a tier freed content even without progress. Restore the baseline dead-end remedy text (image drop is automated now, so the manual /shake images suggestion is stale) and align the rescue-refit regression test with main's continuation gating (auto-continue after compaction now requires an active goal or queued work).
This commit is contained in:
@@ -13904,25 +13904,32 @@ export class AgentSession {
|
||||
// That is exactly the dead-end the elide shake rescues: it reaches
|
||||
// INSIDE the tail and offloads heavy content to an artifact placeholder,
|
||||
// shrinking the tail so findCutPoint can then move the cut and leave
|
||||
// older turns to summarize. Run the same rescue the post-maintenance
|
||||
// guard uses, then re-prepare on the elided branch and fall through to
|
||||
// the normal compaction body when it now succeeds (writing a compaction
|
||||
// entry anchors the stale billed usage so the auto-continue re-check
|
||||
// cannot re-trip and loop the warning — issue #4786). Skip when we
|
||||
// already fell through from a shake strategy pass (it tried and found
|
||||
// nothing) or on the idle timer (it re-checks usage on its own cadence).
|
||||
let rescued: ShakeResult | undefined;
|
||||
if (reason !== "idle" && !fallbackFromShake) {
|
||||
rescued = await this.#tryShakeRescueForDeadEnd(autoCompactionSignal);
|
||||
if (rescued && !autoCompactionSignal.aborted) {
|
||||
pathEntriesForCompaction = this.sessionManager.getBranch();
|
||||
preparation = prepareCompaction(
|
||||
pathEntriesForCompaction,
|
||||
compactionSettings,
|
||||
autoCompactionCandidates,
|
||||
);
|
||||
if (preparation) this.#emitShakeRescueNotice(rescued);
|
||||
}
|
||||
// older turns to summarize. Run the same tiered rescue the
|
||||
// post-maintenance guard uses (elide, then image drop), with progress
|
||||
// defined as "prepareCompaction now succeeds on the rewritten branch",
|
||||
// and fall through to the normal compaction body when it does (writing
|
||||
// a compaction entry anchors the stale billed usage so the
|
||||
// auto-continue re-check cannot re-trip and loop the warning — issue
|
||||
// #4786). `skipElide` when we already fell through from a shake
|
||||
// strategy pass (it tried and found nothing); skip entirely on the
|
||||
// idle timer (it re-checks usage on its own cadence).
|
||||
let rescueRewroteHistory = false;
|
||||
if (reason !== "idle") {
|
||||
await this.#rescueCompactionDeadEnd(autoCompactionSignal, {
|
||||
skipElide: fallbackFromShake,
|
||||
hasProgress: () => {
|
||||
// Only reached when a tier actually freed something, so the
|
||||
// branch has been rewritten either way.
|
||||
rescueRewroteHistory = true;
|
||||
pathEntriesForCompaction = this.sessionManager.getBranch();
|
||||
preparation = prepareCompaction(
|
||||
pathEntriesForCompaction,
|
||||
compactionSettings,
|
||||
autoCompactionCandidates,
|
||||
);
|
||||
return preparation !== undefined;
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!preparation) {
|
||||
await this.#emitSessionEvent({
|
||||
@@ -13946,7 +13953,7 @@ export class AgentSession {
|
||||
if (noProgressDeadEnd) {
|
||||
this.emitNotice(
|
||||
"warning",
|
||||
compactionDeadEndWarning("clear large tool output, run `/shake images` to drop attached images,"),
|
||||
compactionDeadEndWarning("shrink it (e.g. clear large tool output)"),
|
||||
"compaction",
|
||||
);
|
||||
}
|
||||
@@ -13959,7 +13966,7 @@ export class AgentSession {
|
||||
: noProgressDeadEnd
|
||||
? COMPACTION_CHECK_BLOCK_AUTOMATIC_CONTINUATION
|
||||
: COMPACTION_CHECK_NONE;
|
||||
return rescued ? { ...base, historyRewritten: true } : base;
|
||||
return rescueRewroteHistory ? { ...base, historyRewritten: true } : base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1345,8 +1345,10 @@ describe("AgentSession auto-compaction progress guard", () => {
|
||||
// side) and summary compaction cannot start. The dead-end runs the elide
|
||||
// shake rescue INSIDE the tail; once it frees enough, prepareCompaction is
|
||||
// retried on the elided branch, now succeeds, and the pass falls through to
|
||||
// a normal (hook-supplied) compaction that creates headroom and
|
||||
// auto-continues instead of looping the no-progress warning.
|
||||
// a normal (hook-supplied) compaction that creates headroom and — with an
|
||||
// active goal still needing work — auto-continues instead of looping the
|
||||
// no-progress warning.
|
||||
activateOngoingGoal("rescue-refit");
|
||||
const branch = sessionManager.getBranch();
|
||||
const firstKeptEntryId = branch[branch.length - 1].id;
|
||||
if (!firstKeptEntryId) throw new Error("seeded entry has no id");
|
||||
|
||||
Reference in New Issue
Block a user