opencode-acp 1.8.2 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -421,6 +421,49 @@ For the complete list with root cause analysis, see the [bug tracker](https://gi
421
421
 
422
422
  ## Changelog
423
423
 
424
+ ### v1.9.1 — Disjoint Visible-Range Segments & Nudge Wording (issue #9 root cause)
425
+
426
+ **Problem**: Even after v1.9.0, the model kept calling `compress` against IDs that a prior block had consumed. The root cause was that the suffix advertised a single contiguous span "first visible → last visible" that **straddled compression holes** — so the model's first guess for an `endId` landed inside an already-summarized range. Separately, the suffix's `(+X tokens since last nudge)` growth line was being misread as an *overflow* warning, triggering panic compressions of large-but-still-needed ranges.
427
+
428
+ **Fix 1 — disjoint visible-id segments** (PR #57): `injectVisibleIdRange` no longer emits one "first-to-last" span. It builds the actual surviving segments in ascending ref order and truncates to the largest tool-bearing / high-token segments when the count overflows (`compress.maxVisibleSegments`, default `50`, now plumbed through config defaults + merge + validation + schema). The suffix now reads e.g. `[Visible (top 2 of 3 segments, 803 msgs): m00001–m00929, m00944–m00950 | +1 smaller segment (~1.2K tokens, 6 msgs) omitted]`, so the model sees exactly which ranges are compressible and never targets a hole. The formatting logic is extracted into pure, exported, unit-tested functions (`buildVisibleSegments`, `formatVisibleGuidance`).
429
+
430
+ **Fix 2 — nudge wording** (PR #58): The incremental-compression guidance line (`💡 Compress incrementally: target the ranges above...`) moved to *after* the largest-ranges list and is reworded to stress that **size alone is not a reason to compress** — a large range that is still needed in full must be kept. Soft efficiency nudges (`growth` / `minLimit` variants) are now prefixed with an explicit *"This is an efficiency nudge to compress early and keep context lean — not an overflow warning. A separate, stronger alert will appear if the context is actually full."* so the growth delta isn't mistaken for an overflow alarm. The `maxLimit` path keeps its stronger alert and is intentionally excluded from the efficiency framing.
431
+
432
+ **Compatibility**: No persisted-state schema changes. New optional config field `compress.maxVisibleSegments` (number, default `50`); old configs keep working.
433
+
434
+ ---
435
+
436
+ ### v1.9.0 — Visible-Range Guidance & Compression Failure Recovery
437
+
438
+ **Problem**: On large-context models (1M+) the model repeatedly called `compress(startId=m00930, endId=m00943)` against IDs that a prior block had already consumed. It had no stable view of which `mNNNNN` refs were still compressible, the failure error gave no recovery info, `acp_status` was registered but never mentioned in the prompt, and the suffix nudge reported a bare percentage with no indication of *where* the tokens were actually spent.
439
+
440
+ **System prompt rewrite**:
441
+ - All four context tools (`compress`, `decompress`, `search_context`, `acp_status`) now listed with a one-line "when to use" hint each.
442
+ - Explicit compress / do-not-compress scenes replace the imperative "compress obvious waste promptly" wording.
443
+ - New **CONTEXT BREAKDOWN** section explains the 4-category suffix format (`tool | summaries | code | text`), the largest-range candidates, and the incremental "one large consumed range per call" strategy.
444
+ - Batch-compression guidance: aim for 20+ messages per `compress` call rather than many small summaries.
445
+ - New **task-phase-end** trigger: when a bug hunt / exploration / research sprint ends, compress the phase's redundant churn while preserving findings, file paths, and decision rationale.
446
+
447
+ **Nudge cadence**:
448
+ - Dropped the `contextPct >= 15%` floor entirely. Cadence is now pure 5%-of-limit growth with a first-turn baseline (no more forced nudge on turn 1).
449
+ - Baseline auto-resets after a significant post-compression token drop, so the next nudge fires on the post-compression level instead of waiting a full growth cycle.
450
+ - Suffix nudge gains a **3-category composition breakdown** (`tool | summaries | code | text`, no double-counting of code-bearing messages) plus the **largest ranges** in the tool and code categories — concrete compression targets, not a bare percentage.
451
+
452
+ **`acp_status` upgrade**: accepts `mode` (`summary` | `detailed`), `sort` (`recent` | `size` | `age`), and `limit`. Each block row shows `compressedTokens→summaryTokens` and the `mNNNNN` range it consumed.
453
+
454
+ **Compress failure recovery**: `resolveBoundaryIds` failures now return the current visible range (first/last ref), the active block count, and a pointer to `acp_status`. Out-of-range `endId` guesses (unregistered refs that parse higher than the last visible message) are **clamped** to the last visible message instead of failing; refs that are registered but already consumed still fail with the recovery hint (clamping them would silently recompress summarized content).
455
+
456
+ **Hardening**:
457
+ - `maxSummaryLengthHard` default raised `4000 → 8000 → 10000`; the compress-tool schema now sources its display value from config so changes propagate.
458
+ - Removed the stale `MODEL_CONTEXT_LIMITS` 38-entry fallback table — `modelContextLimit` is now sourced solely from the host SDK's `input.model.limit.context`. Providers that omit the field surface `undefined` immediately rather than getting a distorted percentage from a stale guess.
459
+ - `.catch()` added to every fire-and-forget `saveSessionState` call; removed an `anchorsChanged`-on-baseline path that triggered a concurrent-save race.
460
+ - `STORAGE_DIR` made dynamic (re-evaluates `XDG_DATA_HOME` at call time) so relocated data dirs and test harnesses work.
461
+ - Compression summaries now injected as assistant-role messages with system-metadata tags.
462
+
463
+ **Compatibility**: No persisted-state schema changes. `minNudgeContextPercent` config field preserved as a no-op for old configs.
464
+
465
+ ---
466
+
424
467
  ### v1.8.2 — Always Inject System Prompt
425
468
 
426
469
  **Bug fix**: System prompt gating (v1.8.1 commit `24bbb1f`) caused binge compression on large-context models. Since ACP injections are ephemeral (not persisted to conversation history), gating the system prompt made the model completely forget compression tools existed between nudges. When the nudge fired after 50K growth, the model panicked and made 95 consecutive compress calls.
package/README.zh-CN.md CHANGED
@@ -393,6 +393,49 @@ ACP 在首次启动时自动将配置从 `dcp.jsonc` 迁移到 `acp.jsonc`,将
393
393
 
394
394
  ## 更新日志
395
395
 
396
+ ### v1.9.1 — 不相交可见范围段 & 提醒措辞修正(issue #9 根因)
397
+
398
+ **问题**:即便有了 v1.9.0,模型仍反复对已被先前块消费的 ID 调用 `compress`。根因是 suffix 一直广播一条"从首条可见到最后一条可见"的**跨越压缩空洞的连续 span** —— 模型对 `endId` 的第一反应往往是落在已经被摘要的范围里。此外,suffix 的 `(+X tokens since last nudge)` 增长行被误读为**溢出警告**,触发对"大但仍然需要"范围的恐慌性压缩。
399
+
400
+ **修复 1 — 不连续可见 ID 段**(PR #57):`injectVisibleIdRange` 不再输出一条"首到尾"span。改为按引用升序构建真正存活的不相交段,并在段数溢出时截断到最大的含工具 / 高 token 段(`compress.maxVisibleSegments`,默认 `50`,已通过 config defaults + merge + validation + schema 全链路接入)。suffix 现在形如 `[Visible (top 2 of 3 segments, 803 msgs): m00001–m00929, m00944–m00950 | +1 smaller segment (~1.2K tokens, 6 msgs) omitted]`,模型能精确看到哪些范围可压缩、绝不会被引导去打空洞。格式化逻辑抽取为纯函数并导出、可单测(`buildVisibleSegments`、`formatVisibleGuidance`)。
401
+
402
+ **修复 2 — 提醒措辞**(PR #58):增量压缩指引行(`💡 Compress incrementally: target the ranges above...`)移到 largest-ranges 列表**之后**,并改写以强调**仅凭大小不是压缩理由** —— 仍然需要完整保留的大范围必须保留。软性效率提醒(`growth` / `minLimit` 变体)现在前置一条明确说明 *"This is an efficiency nudge to compress early and keep context lean — not an overflow warning. A separate, stronger alert will appear if the context is actually full."*,使增长量不被误读为溢出警报。`maxLimit` 路径保留更强的告警,并有意排除在效率措辞之外。
403
+
404
+ **兼容性**:无持久化 state schema 变更。新增可选配置字段 `compress.maxVisibleSegments`(数字,默认 `50`);旧配置继续工作。
405
+
406
+ ---
407
+
408
+ ### v1.9.0 — 可见范围引导 & 压缩失败恢复
409
+
410
+ **问题**:在大上下文模型(1M+)上,模型反复调用 `compress(startId=m00930, endId=m00943)`,而这些 ID 已被之前的块消费。模型对哪些 `mNNNNN` 引用仍可压缩没有稳定视图,失败错误不提供恢复信息,`acp_status` 工具已注册但从未在提示中提及,suffix nudge 只报告一个裸百分比,完全不说明 token 实际花在了哪里。
411
+
412
+ **系统提示重写**:
413
+ - 四个上下文工具(`compress`、`decompress`、`search_context`、`acp_status`)现在每个都带一行"何时使用"提示。
414
+ - 显式的"压缩 / 不压缩"场景替代了命令式的"promptly 压缩明显垃圾"措辞。
415
+ - 新增 **CONTEXT BREAKDOWN** 章节,解释 4 类后缀格式(`tool | summaries | code | text`)、最大范围候选项,以及"每次调用针对一个已消费的大范围"的增量策略。
416
+ - 批量压缩引导:每次 `compress` 调用尽量覆盖 20+ 条消息,而不是产生许多小摘要。
417
+ - 新增 **task-phase-end** 触发器:当一次 bug 排查 / 探索 / 研究冲刺结束时,主动压缩该阶段的冗余翻腾,同时保留关键发现、文件路径、决策依据。
418
+
419
+ **Nudge 频率**:
420
+ - 彻底移除 `contextPct >= 15%` 下限。频率现在纯粹是 5%-of-limit 增长,首轮建立基线(不再在第 1 轮强制触发)。
421
+ - 基线在压缩后 token 显著下降时自动重置,使下一次 nudge 在压缩后的水平触发,而不是等满一个完整增长周期。
422
+ - suffix nudge 新增 **3 类组成分解**(`tool | summaries | code | text`,不再对含 code 的消息双重计数),加上 tool 和 code 类别的**最大范围**列表 —— 具体的压缩目标,而不是裸百分比。
423
+
424
+ **`acp_status` 升级**:接受 `mode`(`summary` | `detailed`)、`sort`(`recent` | `size` | `age`)、`limit`。每个块行显示 `compressedTokens→summaryTokens` 以及它消费的 `mNNNNN` 范围。
425
+
426
+ **压缩失败恢复**:`resolveBoundaryIds` 失败现在返回当前可见范围(首/尾引用)、活跃块数,以及指向 `acp_status` 的指引。超出范围的 `endId` 猜测(未注册但解析值高于最后一条可见消息的引用)会被**钳制**到最后一条可见消息,而不是失败;已注册但已被消费的引用仍然失败并附恢复提示(钳制它们会静默重新压缩已摘要的内容)。
427
+
428
+ **加固**:
429
+ - `maxSummaryLengthHard` 默认值提升 `4000 → 8000 → 10000`;compress 工具 schema 现在从 config 取显示值,配置变更能传播。
430
+ - 移除陈旧的 `MODEL_CONTEXT_LIMITS` 38 项回退表 —— `modelContextLimit` 现在仅来自 host SDK 的 `input.model.limit.context`。省略该字段的 provider 会立即暴露 `undefined`,而不是从陈旧猜测中得到扭曲的百分比。
431
+ - 所有 fire-and-forget `saveSessionState` 调用添加 `.catch()`;移除了触发并发保存竞态的 baseline `anchorsChanged` 路径。
432
+ - `STORAGE_DIR` 改为动态(在调用时重新求值 `XDG_DATA_HOME`),使重定位的数据目录和测试 harness 能正常工作。
433
+ - 压缩摘要现在以 assistant 角色 + system-metadata 标签注入。
434
+
435
+ **兼容性**:无持久化 state schema 变更。`minNudgeContextPercent` 配置字段作为 no-op 保留以兼容旧配置。
436
+
437
+ ---
438
+
396
439
  ### v1.8.2 — 始终注入系统提示词
397
440
 
398
441
  **Bug 修复**:系统提示词门控(v1.8.1 commit `24bbb1f`)导致大上下文模型 binge 压缩。由于 ACP 注入是临时的(不持久化到对话历史),gate 掉系统提示词会让模型在两次 nudge 之间完全忘记压缩工具的存在。当 50K 增长后 nudge 触发时,模型恐慌性连续调用 95 次压缩。