Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
c54c9d2
fix(#5175): strip drifted open-tag names and mid-turn draft envelopes
Louie0806 Oct 29, 2026
c507717
fix(#5175): adjudicate the SSE lane's released spans against drift tags
Louie0806 Oct 30, 2026
4225a1e
fix(#5175): never read the kernel's own protocol tags as drift
Louie0806 Oct 30, 2026
fff60bc
fix(#5175): keep the signed-thinking channel out of the drift adjudic…
Louie0806 Oct 30, 2026
ba23a29
test(#5176): pin the #2303 retry's measured limit — streamed draft by…
Louie0806 Oct 30, 2026
7bee49a
chore(#5175): drop a dead drift-tail constant left from an abandoned arm
Louie0806 Oct 30, 2026
2ed07a4
fix(#5175): route complete drifted units past the streaming fast path
Louie0806 Oct 30, 2026
fc402db
test(#5175): drive the REAL pipeline, because a hand-rolled copy hid …
Louie0806 Oct 30, 2026
91ef058
fix(storage): name the sidecar's db path with native separators
Louie0806 Oct 30, 2026
cadbf77
docs(#4788): seed sessions.hardMaxBytes so the config guards stop fai…
Louie0806 Oct 30, 2026
d7f8489
fix(#4788): keep the debounce timer referenced while a caller waits f…
Louie0806 Oct 30, 2026
3eb22b1
test(#4666): pin the mysql lock lane to the CURRENT schema version, n…
Louie0806 Oct 30, 2026
dda8379
test(#4788): close the unified sidecar before the teardown unlink
Louie0806 Oct 30, 2026
cc418fb
test(#5140): state the unified-mode precondition instead of inheritin…
Louie0806 Oct 30, 2026
8c4f711
fix(#5175): judge each attempt on its own output; only an unfinished …
Louie0806 Oct 30, 2026
6f2f6ca
test(#5152): publish the receiver port atomically so polling cannot r…
Louie0806 Oct 30, 2026
a5a71ea
Merge upstream/master into 2026-10-30_drifted-name-leak
Louie0806 Oct 30, 2026
4ea57ea
test(#5155): await the turn's durable save instead of a fixed 20ms sleep
Louie0806 Oct 30, 2026
a1450f6
docs(#4788): regenerate CONFIGURATION.md from the backticked seed aft…
Louie0806 Oct 30, 2026
6aecc25
fix(#5175): adjudicate drifted render-tag residue on the responses wire
Louie0806 Oct 30, 2026
63bedca
Merge branch 'master' of ranxianglei/billion-context into 2026-10-30_…
Louie0806 Oct 31, 2026
e814cad
Merge remote-tracking branch 'refs/remotes/upstream/master' into 2026…
Louie0806 Oct 31, 2026
095b39b
fix(#5175): own the attribute-slot pair whose closing name disagrees
Louie0806 Oct 31, 2026
8a66c6f
Merge remote-tracking branch 'refs/remotes/upstream/master' into HEAD
Louie0806 Oct 31, 2026
5dd03ac
fix(#5175): own the bare-ref attribute pair whose closing name disagrees
Louie0806 Oct 31, 2026
3121f5a
Merge remote-tracking branch 'refs/remotes/upstream/master' into 2026…
Louie0806 Oct 31, 2026
714d69a
fix(#5175): stop convicting the anonymous empty pair — it is valid XML
Louie0806 Oct 31, 2026
aa83ef4
Merge remote-tracking branch 'refs/remotes/upstream/master' into 2026…
Louie0806 Oct 31, 2026
f24dd45
Merge remote-tracking branch 'refs/remotes/upstream/master' into 2026…
Louie0806 Oct 31, 2026
595b984
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
22c5596
docs(#4125): seed the two env names the lifecycle ledger guard reads …
Louie0806 Oct 31, 2026
be9e580
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
985632c
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
f65dd4e
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
50aef1a
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
4f7fb2f
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
d5c7d26
test(#5175): pin the last-mile invariant — prose is cut-independent, …
Louie0806 Oct 31, 2026
76673c3
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
0bd9127
refactor(#5175): drop the dead attested parameter from stripDriftPair…
Oct 31, 2026
a7e5211
test(#5175): make the verbatim-channel assertion a real tripwire
Louie0806 Oct 31, 2026
c811264
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
e154f78
fix(ci): clear the three master-red gates — two unused exports + the …
Louie0806 Oct 31, 2026
db85e78
Merge the master-red gate fixes into the drift-leak branch
Louie0806 Oct 31, 2026
f5ddd36
fix(ci): clear the two remaining master-red test shards — windows npm…
Louie0806 Oct 31, 2026
1b0726e
Merge branch '2026-10-31_master-red-gates' into 2026-10-30_drifted-na…
Louie0806 Oct 31, 2026
4e0523e
fix(#4788): a discharged content-store proxy must not turn the next t…
Louie0806 Oct 31, 2026
0d6390a
merge: upstream/master into the drifted-name-leak lane
Louie0806 Oct 31, 2026
045ac89
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
8635c28
chore: drop rows master already registers and a now-dead gate allowli…
Louie0806 Oct 31, 2026
0de20ef
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
b51d688
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
f85de2b
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
691b14c
fix(#5345): restore the {need} placeholder and teach the i18n dead-ke…
Louie0806 Oct 31, 2026
8a3a964
Merge upstream/master (0caccf29e): adopt the upstream pack-editor i18…
Louie0806 Oct 31, 2026
906ccd5
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
adc94d7
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
da31a09
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
1050231
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
7d2b5e0
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
885a5f5
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Oct 31, 2026
b1f78da
test(#5175): pin defect A on the anthropic wire, the lane with no tri…
Louie0806 Oct 31, 2026
2a9296c
test(#5175): pin defect A on the google wire, the third independent f…
Louie0806 Oct 31, 2026
eeb7eb4
test(#5175): pin the cross-cut invariant per chat lane
Louie0806 Oct 31, 2026
e5e94de
test(#5175): pin the cross-cut invariant on the responses wire too
Louie0806 Oct 31, 2026
307b509
test(#5175): pin defect B's retraction limit on all four wires, not j…
Louie0806 Oct 31, 2026
1118f35
docs(#5175): drop the two stale DRIFT_EMPTY_MISMATCH references
Louie0806 Oct 31, 2026
6403897
docs(#5175): correct the releaseProse note — it is orphan-close clean…
Louie0806 Oct 31, 2026
a7a3657
test(#5175): cover the non-streaming JSON seam, the one lane with no …
Louie0806 Oct 31, 2026
e0e9c57
fix(#5175): strip render-tag residue on the native-compaction JSON eg…
Louie0806 Nov 1, 2026
d8629e9
Merge remote-tracking branch 'upstream/master' into 2026-10-30_drifte…
Louie0806 Nov 1, 2026
aa159c2
docs(#5175): the stripOpenaiChatText header promised a channel the co…
Louie0806 Nov 1, 2026
404aced
docs(#5175): record why the streaming filter runs three drift rules, …
Louie0806 Nov 1, 2026
b007887
docs(#5175): record why no span-local rule narrows the streaming resi…
Louie0806 Nov 1, 2026
f97fdcc
test(#5175): cover the four non-streaming JSON rewriters, the fifth seam
Louie0806 Nov 1, 2026
c70fcaf
test(#5175): drop the dead streamThrough harness left by the real-pip…
Nov 1, 2026
8d5fb80
fix(#5175): draft-dump gate wording covers the envelope form (log + c…
Nov 1, 2026
443e3b4
Merge upstream/master (c78ecb4b5): adopt #5408 frozen-envelope recove…
Louie0806 Nov 1, 2026
a5c07c2
Merge upstream/master (fad9805bc): adopt #5506 metadata-fold gate + #…
Louie0806 Nov 2, 2026
1124d97
Merge upstream master (3a2d051ec): adopt #5520 gate-local evidence ch…
Louie0806 Nov 2, 2026
76d64a4
Merge upstream/master (d5a84f165): adopt #5522 anthropic follow-side …
Louie0806 Nov 2, 2026
abea771
Merge upstream/master (00006b553): adopt #5531/#5535 turn-integrity +…
Louie0806 Nov 2, 2026
f68e894
Merge upstream/master (7f6ad2237): adopt #5469 full-resend watermark …
Louie0806 Nov 2, 2026
18c099f
Merge upstream/master (daa082ead): adopt release v0.1.212 + wm-notice…
Louie0806 Nov 2, 2026
09f26d0
Merge upstream/master (db73897a4): adopt #5518 inclusive-selfcheck re…
Louie0806 Nov 2, 2026
ef3c88d
Merge upstream/master (dec393f43): adopt #5496 unsigned-thinking repl…
Louie0806 Nov 2, 2026
33a212b
Merge upstream/master (d244ffff2): adopt #5556 false-ad copy sweep + …
Louie0806 Nov 3, 2026
cac717d
Merge upstream/master (e10c7586b): adopt #5612 Qoder model-name norma…
Louie0806 Nov 3, 2026
b9c3d19
Merge upstream/master (6a06abf2c): adopt #5559 kernel false-ad batch …
Louie0806 Nov 3, 2026
8f38748
Merge upstream/master (c29b118d1): adopt the unified notice surface (…
Louie0806 Nov 4, 2026
7961707
Merge upstream/master (5dee4850b): adopt the storage forensics, repet…
Louie0806 Nov 4, 2026
8279be4
Merge upstream/master (1b7a661a2): adopt the pi inline-posture defaul…
Louie0806 Nov 4, 2026
778eef0
Merge upstream/master (23a826d37): adopt the ref-recoverable media fo…
Louie0806 Nov 4, 2026
247e482
Merge upstream/master (c9ba48566): adopt the dsh profile refresh veri…
Louie0806 Nov 4, 2026
3c6dfbc
Merge upstream/master (0aace2f20): adopt #5683 unprompted-compress ga…
Louie0806 Nov 5, 2026
e3a5972
Merge upstream/master (6ddade163): adopt #5698 T1 harvest-stall escal…
Louie0806 Nov 5, 2026
ac4d1ae
Merge upstream/master (9a2d51d65): adopt #5718 sidecar-residual reali…
Louie0806 Nov 5, 2026
1a1c975
Merge upstream/master (bfabcd1ca): adopt #5539 FK content indexes and…
Louie0806 Nov 5, 2026
e0a1e4b
Merge upstream/master (84fa9af5f): adopt #5758 kernel tool-pair id wi…
Louie0806 Nov 6, 2026
d777320
Merge upstream/master (be611a856): adopt dsh injection-slot exclusion…
Louie0806 Nov 6, 2026
7be28fc
Merge upstream/master (be611a856 -> c3dfbe6b2): adopt #5814 authored-…
Louie0806 Nov 6, 2026
65665ab
Merge upstream/master (c3dfbe6b2 -> c2797c33b): adopt #5789 tier-dist…
Louie0806 Nov 7, 2026
c797683
Merge upstream/master (d640d0d06): adopt #4900 fork-thinking-gate, #5…
Louie0806 Nov 7, 2026
9f96c14
Merge upstream/master (ce8f92ef3): adopt fastpath-v6 identity, image-…
Louie0806 Nov 7, 2026
42cee0f
Merge upstream/master (bebc239f2): follow the #5854 revert of the fas…
Louie0806 Nov 7, 2026
41f71fe
Merge upstream/master (21c950ef0): adopt the #5843 batch + the #5719 …
Louie0806 Nov 7, 2026
d3e89c5
Merge upstream/master (df0a4023b): adopt #5842 identity-channel wirin…
Louie0806 Nov 7, 2026
1e1016b
Merge upstream/master (5af5f9fed): adopt #5756 lazy historian sweep
Louie0806 Nov 7, 2026
e43ff6a
Merge origin/ci-fixes: converge post-#5860 golden realignment (#4599 …
Nov 7, 2026
2cfb835
Merge upstream/master (2bda6b336): adopt #5882 estimate-hold backstop…
Louie0806 Nov 7, 2026
3fd455d
Merge upstream/master (6945a354d): adopt #5744 incremental refs ledge…
Louie0806 Nov 7, 2026
70b8092
Merge upstream/master (cda6e7350): adopt #5895 P2 review batch; relay…
Louie0806 Nov 7, 2026
b08915b
fix: correct stale schema-plane comment in issue4666 dedup test
bot Nov 7, 2026
5d5e795
Merge upstream/master (133f3525c): adopt #5902 P2 review fixes and th…
Louie0806 Nov 7, 2026
4e16b45
Merge upstream/master (c168d9be0): adopt the window-fallback docs fix
Louie0806 Nov 8, 2026
5a8ffa7
Merge upstream/master (6df7ae15e): adopt the #5898 review batch and t…
Louie0806 Nov 8, 2026
f158fd7
Merge upstream/master (354e21e23): adopt the dsh lane small-fixes bat…
Louie0806 Nov 8, 2026
ca477cb
Merge upstream/master (48ee6a758): adopt the docs centralization and …
Louie0806 Nov 8, 2026
99dbe9c
ci: retrigger — windows shard 4 flaked on the inherited event-loop-wa…
Louie0806 Nov 8, 2026
84bc331
ci: retrigger — two different inherited Windows flakes in consecutive…
Louie0806 Nov 8, 2026
62ed8af
Merge upstream/master (3ac3e95c0): adopt the docs hub, the slimmed AG…
Louie0806 Nov 8, 2026
f61a6d1
Merge upstream/master (fe963d7f5): adopt the measured outbound-body e…
Louie0806 Nov 8, 2026
a2816be
Merge upstream/master (f1a4af4ee): adopt first-byte replay, log-mask …
Louie0806 Nov 8, 2026
2d1752e
Merge upstream/master (82e2d53c6): adopt shredded-merge dead-end reco…
Louie0806 Nov 8, 2026
0b0e35c
Merge upstream/master (848f59b99): adopt the CI test-signal batch (gu…
Louie0806 Nov 8, 2026
267cc77
Merge upstream/master (33d495180): adopt #5963 context analysis, #594…
Louie0806 Nov 9, 2026
b76e8dc
Merge upstream/master (7d18b7ab9): adopt #5659 pi.commands, #5970 ret…
Louie0806 Nov 9, 2026
2fee6ab
Merge upstream/master (1f311dd8d): adopt #5986 degenerate whitespace …
Louie0806 Nov 9, 2026
15690d0
test(ci): register issue5955 wedged-takeover suite in LIVE_FILES (#12…
Nov 9, 2026
c7da038
Merge upstream/master (39fc2eeff): adopt #5996 empty-slot window refu…
Louie0806 Nov 9, 2026
421da3c
Merge upstream/master (5c3c2688f): adopt #6001 root README locale tra…
Louie0806 Nov 9, 2026
242b192
Merge upstream/master (406193b20): adopt #6004 Japanese README transl…
Louie0806 Nov 9, 2026
244f5e8
fix(#5179): strip the acp_tokens count-shape render-tag emission (who…
Nov 9, 2026
c6eaf1f
fix(#5179): draft-dump lane log/comment wording covers the envelope form
Nov 9, 2026
e374969
test(#5179): pin the deliberate acp-prefix width of the count-shape rule
Nov 9, 2026
ef41839
Merge upstream/master (63a40600e): adopt #6015 iot-thinking incompati…
Louie0806 Nov 9, 2026
172a7ca
Merge remote-tracking branch 'refs/remotes/origin/master' into wt-pr5…
Nov 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ This index is generated from `website/config-reference/*.yaml` — edit the seed
| `compress.maxSummaryLength` | number | kernel 20000 | — | Hard character cap on ONE generated summary; longer replies are rejected whole (no truncation, no retry). External summarizers are told this exact cap up front (#3635). 0 = unbounded. |
| `compress.minSummaryLength` | number | kernel 50 | — | Character floor for generated summaries: a single range must meet it alone; a multi-range batch passes when its combined summaries reach it (#5894). 0 = disabled. External summarizers remain held to the per-summary floor (#3635). |
| `compress.reconcile` | "off" \| "warn" \| "repair" | "repair" | BILI_FOLD_RECONCILE | Reconcile folded state when the client rewinds or rewrites history between turns. |
| `compress.promptPack` | string (builtin: "default", "lean") | builtin "default" | — | Compression prompt pack, resolved project pack → user pack → builtin; not gated by acknowledgePromptsRisk. |
| `compress.promptPack` | string (builtin: "default", "lean", "chat") | builtin "default" | — | Compression prompt pack, resolved project pack → user pack → shipped pack → builtin; not gated by acknowledgePromptsRisk. |
| `compress.tiers` | boolean | true | — | Tiered T1→T3 distillation spreads folding cost across generations. |
| `compress.protectedTools` | string[] | none | — | Hard exclusion across all history: results of listed tools never fold. Path patterns (skill/<name>) select skills by name (#1947). |
| `compress.protectedLatestTools` | string[] | none | — | Protects only the LATEST instance of cumulative-snapshot tools whose newest result supersedes older ones (e.g. todo lists). Path patterns keep the latest instance per skill (skill/*, #1947). |
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@
| `compress.maxSummaryLength` | number | kernel 20000 | — | 单条生成摘要的硬字符上限;超长的回复被整段拒绝(不截断、不重试)。外部摘要模型会被提前告知这个确切上限(#3635)。0 = 不限制。 |
| `compress.minSummaryLength` | number | kernel 50 | — | 生成摘要的字符下限:单段压缩按自身判定;批量压缩按合计判定——一段偷懒不再拖垮整批(#5894)。0 = 禁用。外部摘要模型仍受逐段下限约束(#3635)。 |
| `compress.reconcile` | "off" \| "warn" \| "repair" | "repair" | BILI_FOLD_RECONCILE | 客户端在轮次之间回退或改写历史时校准已折叠状态。 |
| `compress.promptPack` | string (builtin: "default", "lean") | builtin "default" | — | 压缩提示词包,按 项目包 → 用户包 → 内置 解析;不受 acknowledgePromptsRisk 门控。 |
| `compress.promptPack` | string (builtin: "default", "lean", "chat") | builtin "default" | — | 压缩提示词包,按 项目包 → 用户包 → 随包附带(chat)→ 内置 解析;不受 acknowledgePromptsRisk 门控。 |
| `compress.tiers` | boolean | true | — | T1→T3 分级蒸馏把折叠成本摊到多代。 |
| `compress.protectedTools` | string[] | none | — | 全历史硬排除:列出工具的结果永不折叠。路径模式(skill/<name>)可按名指定 skill(#1947)。 |
| `compress.protectedLatestTools` | string[] | none | — | 只保护累积快照类工具「最新一次」实例(新结果覆盖旧结果的工具,如 todo 列表)。路径模式按 skill 分组各保最新(skill/*,#1947)。 |
Expand Down
35 changes: 35 additions & 0 deletions src/degenerate-turn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,44 @@ export function degenerateTurnWarning(o: TurnOutcome): string | null {
// different defect class — #1755/#2190 — and stay out of scope), case-
// insensitive (#1731 case drift), trailing whitespace allowed.
const DRAFT_CLOSE_TAIL = /\x3c\/(?:summary|analysis)\x3e\s*$/i;
// #5175: the envelope form. When the model writes the WHOLE draft as prose the
// close above is not at the end of the text — `</analysis>` is followed by the
// `<summary>` BODY, tens of thousands of characters of it, so the `$` anchor can
// never match and the turn slipped through as an ordinary answer. The envelope
// signature is exactly the ordering the client's compaction contract describes
// ("an <analysis> block followed by a <summary> block"): an analysis close
// IMMEDIATELY followed by a summary open, whitespace between them. Corpus census
// (8225 fields, 462 sessions): 25 fields carry it, 5 carry the full open…close
// envelope, and only ONE — the already-handled tail form — ends with it. Nothing
// else in the corpus produces that adjacency, so it cannot false-positive on
// prose that merely mentions the words.
const DRAFT_ENVELOPE = /\x3c\/analysis\x3e\s*\x3csummary\x3e/i;
const SUMMARY_CLOSE = /\x3c\/summary\x3e/i;
export function endsWithDraftClose(text: string): boolean {
return text.length > 0 && DRAFT_CLOSE_TAIL.test(text);
}
/** #5175: the draft-envelope shape — a handoff/compression draft written as
* prose in either of its two observable forms: the closing tag at the very end
* (#2303), or the analysis→summary envelope (#5175). Both mean the model
* narrated the action instead of issuing it, so both are non-converged.
*
* The envelope counts only while the draft is UNFINISHED. A complete
* `</analysis><summary>…</summary>` followed by substantive prose delivered
* BOTH the draft and an answer — the turn converged, and re-issuing it appends
* a duplicate answer on the real chat pipe (measured: pristine master keeps a
* single answer, the unconditional envelope rule produced answer + retry
* answer). The reported dumps are always open-ended — the model stops inside
* the summary body (#5175) or right at the analysis close (#2303) — so recall
* is unchanged: the only hits this gives up are complete drafts that kept
* writing, which are exactly the false positives. */
export function isDraftDump(text: string): boolean {
if (text.length === 0) return false;
if (DRAFT_CLOSE_TAIL.test(text)) return true;
const env = DRAFT_ENVELOPE.exec(text);
if (env === null) return false;
// Still inside the draft: the summary body is truncated mid-flight.
return !SUMMARY_CLOSE.test(text.slice(env.index + env[0].length));
}

// #2612: the #2303 draft-tail shape has a legitimate producer — the CLIENT's
// own summarization request. Claude Code's compaction (/compact, auto-compact,
Expand Down
13 changes: 7 additions & 6 deletions src/loop/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { isStrictReasoningEcho, modelIdOf, normalizeStrictEchoBody } from "../st
import { log as loggerLog } from "../logger.js";
import { promptInputTotal, type WireProtocol } from "../util.js";
import { DEGENERATE_RETRY_NUDGE } from "../degenerate-retry.js";
import { endsWithDraftClose, lastUserSummaryInstruction, requestExpectsProseSummary } from "../degenerate-turn.js";
import { isDraftDump, lastUserSummaryInstruction, requestExpectsProseSummary } from "../degenerate-turn.js";
import { safePrefix, safeSuffix, scrubLoneSurrogateEscapesOnJson } from "../text-safe.js";

export const MAX_LOOP_ROUNDS = 10;
Expand Down Expand Up @@ -1248,9 +1248,10 @@ export async function* runCompressLoop(
}
}

// #2303: a terminal turn that DID deliver visible prose but ends with a
// compression-draft closing tag (summary/analysis close forms) and no
// tool call — the model wrote a handoff/compression draft in prose
// #2303: a terminal turn that DID deliver visible prose but carries a
// compression-draft dump (tail close form, or the analysis-to-summary
// envelope mid-text, #5175) and no tool call — the model wrote a
// handoff/compression draft in prose
// instead of issuing the action it described, most often after the
// upstream cut the final tool call out of the step (149 silent stops /
// 70 sessions, DSH native). Same non-convergence as the zero-visible
Expand All @@ -1273,7 +1274,7 @@ export async function* runCompressLoop(
!ctx.textProtocol &&
assistantText.length > 0 &&
calls.length === 0 &&
endsWithDraftClose(assistantText) &&
isDraftDump(assistantText) &&
// #2612: the client's own compaction request instructs the
// model to answer with a plain-text summary block and no
// tool call — that compliant reply is a draft tail by
Expand All @@ -1283,7 +1284,7 @@ export async function* runCompressLoop(
!signal?.aborted
) {
degenerateRetried = true;
ctx.log(`[acp-loop] round ${round}: terminal turn ends with a compression-draft closing tag and no tool call; retrying once with continuation nudge (#2303)`);
ctx.log(`[acp-loop] round ${round}: terminal turn carries a compression-draft dump (tail or mid-text envelope) and no tool call; retrying once with continuation nudge (#2303)`);
loggerLog("warn", `[acp-loop] draft-tail auto-retry round ${round} (session ${ctx.session.id})`);
const nudge: CoreMessage = {
id: `acp_draft_tail_retry_r${round}`,
Expand Down
Loading
Loading