opencode-acp 1.13.5 → 1.13.6

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
@@ -311,6 +311,9 @@ Each level overrides the previous, so project settings take priority over global
311
311
  "nudgeForce": "soft",
312
312
  // Hard-excluded tool names. The root default is ["skill", "compress"]; an explicit
313
313
  // array replaces the inherited policy. Use [] to compress all tool outputs.
314
+ // "compress" is always force-protected regardless of this setting — its summary
315
+ // parameter is the sole record of compressed conversation and cannot be recovered
316
+ // if lost. Use [] to compress all tool outputs except compress itself.
314
317
  "protectedTools": ["skill", "compress"],
315
318
  // Preserve text wrapped in <protect>...</protect> when compressed
316
319
  "protectTags": false,
@@ -400,7 +403,7 @@ By default, these tools are always protected from pruning:
400
403
 
401
404
  The `protectedTools` arrays in `commands` and `strategies` add to this default list.
402
405
 
403
- For the `compress` tool, `compress.protectedTools` ensures specific tool outputs are **hard-excluded** from compression ranges (v1.10.0+). When the model compresses a range that includes a protected tool message, that message survives intact in visible context — only the surrounding non-protected messages are compressed. The root default is `["skill", "compress"]` (the `compress` entry protects compress tool calls — which carry summaries — from being eaten by subsequent sequential compressions); an explicit array replaces the inherited policy. Use `[]` to allow all completed tool outputs to compress.
406
+ For the `compress` tool, `compress.protectedTools` ensures specific tool outputs are **hard-excluded** from compression ranges (v1.10.0+). When the model compresses a range that includes a protected tool message, that message survives intact in visible context — only the surrounding non-protected messages are compressed. The root default is `["skill", "compress"]` (the `compress` entry protects compress tool calls — which carry summaries — from being eaten by subsequent sequential compressions); an explicit array replaces the inherited policy. **`"compress"` is always force-protected regardless of user config** — its `summary` parameter is the sole record of compressed conversation and cannot be recovered if lost. Setting `[]` protects only `compress`; setting `["task"]` protects `task` and `compress`.
404
407
 
405
408
  ---
406
409
 
@@ -472,6 +475,14 @@ For the complete list with root cause analysis, see the [bug tracker](https://gi
472
475
 
473
476
  ## Changelog
474
477
 
478
+ ### v1.13.6 — Force-Protect Compress Tool Regardless of User Config (PR #188)
479
+
480
+ **Problem**: `compress.protectedTools` uses a replace merge policy (PR #177): a user setting `protectedTools: ["skill"]` or `protectedTools: []` silently removed `"compress"` from the protected list. This made compress summaries — the sole record of compressed conversation — vulnerable to being pruned by subsequent sequential compressions, causing irreversible data loss.
481
+
482
+ **Fix**: Added `FORCE_COMPRESS_PROTECTED = ["compress"]` constant in `lib/config.ts`. In `mergeCompress()`, when a user provides an explicit `protectedTools` array, the constant is spread into the Set to guarantee `"compress"` survives any override. Even `protectedTools: []` now resolves to `["compress"]`. Dual-agent reviewed (Oracle + General, both APPROVE).
483
+
484
+ Files: `lib/config.ts`, `tests/config-protected-tools.test.ts`, `README.md`, `README.zh-CN.md`. 846 tests pass.
485
+
475
486
  ### v1.13.5 — Fix Release CI for Squash Merges (PR #187)
476
487
 
477
488
  **Problem**: The release detection regex in `.github/workflows/release.yml` only matched standard merge commits (`Merge pull request #N from .../YYYY-MM-DD_release-v...`), not squash merges. PRs #182 (v1.13.3) and #186 (v1.13.4) were squash-merged, so the release workflow silently skipped — no tag, no npm publish, no GitHub Release. npm was stuck at 1.13.2 while master had already moved to 1.13.4.
package/README.zh-CN.md CHANGED
@@ -280,6 +280,9 @@ ACP 使用自己的配置文件,按以下顺序搜索:
280
280
  "nudgeForce": "soft",
281
281
  // Hard-excluded tool names. The root default is ["skill", "compress"]; an explicit
282
282
  // array replaces the inherited policy. Use [] to compress all tool outputs.
283
+ // "compress" is always force-protected regardless of this setting — its summary
284
+ // parameter is the sole record of compressed conversation and cannot be recovered
285
+ // if lost. Use [] to compress all tool outputs except compress itself.
283
286
  "protectedTools": ["skill", "compress"],
284
287
  // Preserve text wrapped in <protect>...</protect> when compressed
285
288
  "protectTags": false,
@@ -368,7 +371,7 @@ ACP 暴露六个可编辑的 prompt:
368
371
 
369
372
  `commands` 和 `strategies` 中的 `protectedTools` 数组会添加到此默认列表。
370
373
 
371
- 对于 `compress` 工具,`compress.protectedTools` 确保特定工具的输出被**硬排除**在压缩范围之外(v1.10.0+)。当模型压缩包含受保护工具消息的范围时,该消息完整保留在可见上下文中 — 只有周围的非受保护消息被压缩。根默认值为 `["skill", "compress"]`(`compress` 条目保护携带 summary 的 compress 工具调用,防止被后续顺序压缩吞噬);显式数组会替换继承的策略。使用 `[]` 可允许所有已完成工具的输出被压缩。
374
+ 对于 `compress` 工具,`compress.protectedTools` 确保特定工具的输出被**硬排除**在压缩范围之外(v1.10.0+)。当模型压缩包含受保护工具消息的范围时,该消息完整保留在可见上下文中 — 只有周围的非受保护消息被压缩。根默认值为 `["skill", "compress"]`(`compress` 条目保护携带 summary 的 compress 工具调用,防止被后续顺序压缩吞噬);显式数组会替换继承的策略。**`"compress"` 无论用户如何配置都会被强制保护** — 其 `summary` 参数是已压缩对话的唯一记录,一旦丢失无法恢复。设置 `[]` 仅保护 `compress`;设置 `["task"]` 保护 `task` 和 `compress`。
372
375
 
373
376
  ---
374
377
 
@@ -440,6 +443,14 @@ ACP 在首次启动时自动将配置从 `dcp.jsonc` 迁移到 `acp.jsonc`,将
440
443
 
441
444
  ## 更新日志
442
445
 
446
+ ### v1.13.6 — 强制保护 compress 工具,无视用户配置(PR #188)
447
+
448
+ **问题**:`compress.protectedTools` 使用替换式合并策略(PR #177):用户设置 `protectedTools: ["skill"]` 或 `protectedTools: []` 会静默地从保护列表中移除 `"compress"`。这使得 compress 摘要 — 压缩对话的唯一记录 — 容易被后续的顺序压缩裁剪,导致不可恢复的数据丢失。
449
+
450
+ **修复**:在 `lib/config.ts` 中添加 `FORCE_COMPRESS_PROTECTED = ["compress"]` 常量。在 `mergeCompress()` 中,当用户提供显式 `protectedTools` 数组时,该常量被展开到 Set 中,保证 `"compress"` 在任何覆盖下都保留。即使 `protectedTools: []` 现在也会解析为 `["compress"]`。双 agent 审查通过(Oracle + General,均 APPROVE)。
451
+
452
+ 文件:`lib/config.ts`、`tests/config-protected-tools.test.ts`、`README.md`、`README.zh-CN.md`。846 项测试通过。
453
+
443
454
  ### v1.13.5 — 修复 Release CI 对 Squash Merge 的检测(PR #187)
444
455
 
445
456
  **问题**:`.github/workflows/release.yml` 的发布检测正则只认标准 merge commit(`Merge pull request #N from .../YYYY-MM-DD_release-v...`),不认 squash merge。PR #182(v1.13.3)和 #186(v1.13.4)都是 squash 合并,导致 release workflow 静默跳过 — 没有 tag、没有 npm 发布、没有 GitHub Release。npm 卡在 1.13.2,而 master 已经到了 1.13.4。
package/dist/index.js CHANGED
@@ -1517,6 +1517,7 @@ var DEFAULT_PROTECTED_TOOLS = [
1517
1517
  "edit"
1518
1518
  ];
1519
1519
  var COMPRESS_DEFAULT_PROTECTED_TOOLS = ["skill", "compress"];
1520
+ var FORCE_COMPRESS_PROTECTED = ["compress"];
1520
1521
  function showConfigWarnings(ctx, configPath, configData, isProject) {
1521
1522
  const invalidKeys = getInvalidConfigKeys(configData);
1522
1523
  const typeErrors = validateConfigTypes(configData);
@@ -1765,7 +1766,7 @@ function mergeCompress(base, override) {
1765
1766
  toolOutputNudgeThreshold: override.toolOutputNudgeThreshold,
1766
1767
  iterationNudgeThreshold: override.iterationNudgeThreshold ?? base.iterationNudgeThreshold,
1767
1768
  nudgeForce: override.nudgeForce ?? base.nudgeForce,
1768
- protectedTools: Array.isArray(override.protectedTools) ? [...new Set(override.protectedTools)] : base.protectedTools,
1769
+ protectedTools: Array.isArray(override.protectedTools) ? [.../* @__PURE__ */ new Set([...override.protectedTools, ...FORCE_COMPRESS_PROTECTED])] : base.protectedTools,
1769
1770
  protectTags: override.protectTags ?? base.protectTags,
1770
1771
  protectUserMessages: override.protectUserMessages ?? base.protectUserMessages,
1771
1772
  maxSummaryLengthHard: override.maxSummaryLengthHard ?? base.maxSummaryLengthHard,