Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,20 @@ For the complete list with root cause analysis, see the [bug tracker](https://gi

## Changelog

### v1.14.20 — Post-v1.14.19 fix batch (modelContextLimit lifecycle, inactive-block decompress, logging)

**Problem**: Five clusters of post-v1.14.19 issues: (1) `modelContextLimit` stayed stale after a model switch (#312) — within one LLM request the messages hook runs before the system hook refreshes the limit, and on a catalog miss (fresh instance + failed hydration) the previous model's window survived, so every percentage threshold misfired (#315); (2) `decompress` failed on standalone inactive blocks and inactive blocks were invisible in `acp_status` (#193); (3) a preemptive `acknowledgeRisk: true` (carried over from a non-quality error) hard-failed with "no quality gate rejection is pending" (#301); (4) debug nudge notifications used `sendIgnoredMessage` causing phantom turns, the debug recommendation-filter log spammed every turn, and ERROR/WARN lines only reached the daily log when debug was on (#311, #278, #279).

**Fix**:
- #314 + #315: reconcile `state.modelContextLimit` from the model-limit catalog on model switch; record the (provider, model) identity pair alongside the limit and, on a catalog miss, invalidate it when the request's model identity mismatches (match keeps it; legacy persisted states without an identity are treated as stale — one blind turn per upgraded session). The catalog is extracted to `lib/state/model-limits.ts`; failed hydration now logs (info with entry count on success, warn on zero entries/failure) instead of degrading silently.
- #193: `decompress` accepts standalone inactive blocks (nested-block redirect unchanged) and `decompress toFile` writes the real block content; `acp_status scope=compressed` now lists all blocks with an `[inactive]` marker plus active/inactive counts (overview still shows active blocks only).
- #303: `acknowledgeRisk` without a pending quality-gate rejection is now a no-op with a usage-teaching note instead of an error — only a real quality-gate rejection arms the bypass, so the gate's protection is unchanged.
- #278/#279/#311: debug notifications no longer use `sendIgnoredMessage` (phantom turn loop gone); the recommendation-filter log is gated behind `shouldInject` (no more per-turn noise); ERROR/WARN are written to the daily log even when debug is off.

Files: `lib/compress/range.ts`, `lib/state/model-limits.ts`, `lib/state/types.ts`, `index.ts`, `lib/state/registry.ts`. Tests: 1003 pass.

**Install**: `opencode plugin opencode-acp@latest --global`

### v1.14.19 — Fix release pipeline for real (npm 10 `--ignore-scripts` bug)

**Problem**: v1.14.18 (#306) was merged but still never published — `release.yml` failed at the exact same step. Root cause of the failed fix: the CI runner uses Node 22 (npm 10.9.x), and **npm 10 runs the `prepare` lifecycle hook during `npm pack` even when `--ignore-scripts` is passed**. v1.14.18's fix (`npm pack --ignore-scripts`) works on npm 11 but is a no-op on npm 10. When prepare runs, tsup writes `CLI Building entry: index.ts` to **stdout**, breaking `JSON.parse` in `verify-package.mjs` (`SyntaxError: Unexpected token`).
Expand Down
14 changes: 14 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,20 @@ ACP 是 DCP 的直接替代品。迁移步骤:

## 更新日志

### v1.14.20 — v1.14.19 之后的修复批次(modelContextLimit 生命周期、inactive block 解压缩、日志)

**问题**:五类 v1.14.19 之后发现的问题:(1)`modelContextLimit` 在模型切换后失效(#312)——同一次 LLM 请求内,messages hook 先于 system hook 刷新窗口值,而目录未命中时(新实例 + 水合失败),上一个模型的窗口值会一直残留,导致所有按百分比计算的阈值误触发(#315);(2)`decompress` 对独立的 inactive block 报 `Block not found`,且 inactive block 在 `acp_status` 里完全不可见(#193);(3)预防式 `acknowledgeRisk: true`(从非质量门禁错误里带过来的)直接报错 `no quality gate rejection is pending`(#301);(4)debug nudge 通知用 `sendIgnoredMessage` 触发幽灵回合(#311),debug 推荐过滤日志每回合刷屏,ERROR/WARN 在 debug 关闭时不进日常日志(#311、#278、#279)。

**修复**:
- #314 + #315:模型切换时从模型限制目录重新对齐 `state.modelContextLimit`;目录未命中时记录 (provider, model) 身份对,请求的身份与记录不一致时使窗口值失效(一致则保留;未记录身份的旧持久化状态按失效处理,升级后每个会话盲一轮)。目录提取到 `lib/state/model-limits.ts`;水合失败现在会记日志(成功 info 带条目数,失败 warn),不再静默降级。
- #193:`decompress` 接受独立的 inactive block(嵌套 block 重定向不变);`acp_status scope=compressed` 现在列出所有 block,inactive 的带 `[inactive]` 标记,并显示 active/inactive 计数(overview 仍只显示 active)。
- #303:没有待处理的质量门禁拒绝时,`acknowledgeRisk` 变为 no-op + 用法提示,不再报错 —— 真正的质量门禁拒绝才会武装 bypass,门禁保护不受影响。
- #278/#279/#311:debug 通知不再用 `sendIgnoredMessage`(幽灵回合循环消失);推荐过滤日志改为 `shouldInject` 后才输出(不再每回合刷屏);ERROR/WARN 在 debug 关闭时也写入日常日志。

文件:`lib/compress/range.ts`、`lib/state/model-limits.ts`、`lib/state/types.ts`、`index.ts`、`lib/state/registry.ts`。测试:1003 通过。

**安装**:`opencode plugin opencode-acp@latest --global`

### v1.14.19 — 彻底修复发版流水线(npm 10 `--ignore-scripts` 失效)

**问题**:v1.14.18(#306)已合并但依然没有发布 —— `release.yml` 又在同一步骤失败。v1.14.18 修复失败的根本原因:CI 运行器是 Node 22(npm 10.9.x),而 **npm 10 在 `npm pack` 时即使传了 `--ignore-scripts` 也照样执行 `prepare` 生命周期钩子**。v1.14.18 的修复(`npm pack --ignore-scripts`)在 npm 11 上有效,在 npm 10 上是空操作。prepare 一旦执行,tsup 会把 `CLI Building entry: index.ts` 写到 **stdout**,破坏 `verify-package.mjs` 里的 `JSON.parse`(`SyntaxError: Unexpected token`)。
Expand Down
25 changes: 25 additions & 0 deletions devlog/2026-08-17_release-v1.14.20/REQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# REQ — v1.14.20: Post-v1.14.19 fix batch (modelContextLimit lifecycle, inactive-block decompress, logging)

## Problem

Five clusters of issues reported since v1.14.19:

1. **`modelContextLimit` stays stale after model switch (#312, #315).** Within one LLM request the messages hook runs before the system hook refreshes the limit, and on a catalog miss (fresh instance + failed hydration) the previous model's window survived — every percentage-based threshold misfired.
2. **`decompress` fails on standalone inactive blocks (#193).** A block that became inactive (superseded by a higher-tier compress) could no longer be restored: `Block not found`. Inactive blocks were also invisible in `acp_status`.
3. **Preemptive `acknowledgeRisk: true` errors (#301, #303).** Carrying `acknowledgeRisk: true` from a non-quality error hard-failed with `no quality gate rejection is pending`.
4. **Debug nudge phantom turn loop (#311, #278).** Debug notification used `sendIgnoredMessage`, creating a phantom assistant turn on every nudge.
5. **Log spam + missing errors (#279, #311).** The debug recommendation-filter log fired every turn; ERROR/WARN lines only reached the daily log when debug was enabled.

## Fix

- **#314 + #315**: reconcile `state.modelContextLimit` from the model-limit catalog on model switch; record the (provider, model) identity pair alongside the limit and, on a catalog miss, invalidate it when the request's model identity mismatches (match keeps it; legacy persisted states without an identity are treated as stale — one blind turn per upgraded session). Catalog extracted to `lib/state/model-limits.ts`; failed hydration now logs (info with entry count on success, warn on zero/failure) instead of degrading silently.
- **#193**: `decompress` accepts standalone inactive blocks (nested-block redirect unchanged); `acp_status scope=compressed` now lists all blocks with an `[inactive]` marker plus active/inactive counts (overview still shows active only).
- **#303**: `acknowledgeRisk` without a pending quality-gate rejection is a no-op with a usage-teaching note; only a real quality-gate rejection arms the bypass.
- **#278/#279/#311**: debug notifications no longer use `sendIgnoredMessage`; the recommendation-filter log is gated behind `shouldInject`; ERROR/WARN are written to the daily log even when debug is off.

## Acceptance

- All existing tests pass (1003)
- Release commit touches only `package.json` + lock; changelog + devlog on the release branch
- `./scripts/ci/check-pr.sh` green
- release.yml publishes v1.14.20 to npm `latest` after merge
26 changes: 26 additions & 0 deletions devlog/2026-08-17_release-v1.14.20/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# WORKLOG — v1.14.20

## Commits on this release (8 fix commits since v1.14.19)

1. `df0b194` promote: stable v1.14.19 devlog paperwork
2. `49560d9` fix: write ERROR/WARN to daily log even when debug off (#311)
3. `48b941e` fix: reconcile modelContextLimit on model switch (#312/#314)
4. `bb24e83` review(#314): log hydration outcome + dedupe model-limit catalog (extracted `lib/state/model-limits.ts` `createModelLimitCatalog`)
5. `9abff6f` fix: gate debug recommendation filter log behind shouldInject (#279)
6. `38a1920` fix: debug nudge phantom turn loop — stop sendIgnoredMessage (#278)
7. `2761605` fix(compress): preemptive acknowledgeRisk no-op (#301/#303)
8. `73312f4` fix: inactive block decompress + acp_status visibility (#193)
9. `0a63a10` fix(#312): invalidate stale modelContextLimit on catalog miss (#315)

## Release steps

- Preflight: `npm ci` + typecheck + build + test — 1003 tests pass (`/tmp/preflight-opencode-acp.log`)
- `npm version 1.14.20 --no-git-tag-version` (bump commit on release branch)
- Changelog `### v1.14.20` entries added to `README.md` and `README.zh-CN.md`
- Devlog: this folder (REQ.md + WORKLOG.md)
- Commit `release: v1.14.20 — post-v1.14.19 fix batch (modelContextLimit, inactive-block decompress, logging)`

## Verification

- `./scripts/ci/check-pr.sh 2026-08-17_release-v1.14.20 origin/master` — green
- release.yml publishes v1.14.20 to npm `latest` after merge
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "opencode-acp",
"version": "1.14.19",
"version": "1.14.20",
"type": "module",
"description": "Active Context Pruning — model-driven context management for OpenCode (hardened fork of DCP with 35 bug fixes)",
"main": "./dist/index.js",
Expand Down
Loading