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
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

### v1.18.2 — strip leaked bare ACP refs from assistant text tail + fix silent no-op in Windows path protection

**PR #432 + PR #403.** Two bug fixes bundled — no config or state-format changes.

**1. Leaked bare-ref stripping** (#432, fixes #431):
Models occasionally degenerate at end-of-generation and echo the `<dcp-message-id>` annotation pattern they saw on the last visible message, leaving a **bare ref + garbage** fragment at the end of completed text (e.g., `m00057 <random multilingual text>`). The previous sanitizer only removed complete/incomplete *tags*, so tag-less fragments leaked through, persisted into OpenCode's DB, and re-entered later context and compression summaries.
- New pure function `stripLeakedTrailingRefs(text, { nextMessageRef, nextBlockRef })` (`lib/messages/utils.ts`): single-pass regex scan for **line-leading** bare refs (`m\d{4,5}`, `b[1-9]\d*`); truncates from the first match whose numeric value is ≥ the next-to-allocate bound (`messageIds.nextRef` / `prune.messages.nextBlockId`), trimming trailing whitespace.
- Why "future refs only" is safe: refs are strictly monotonic — output produced before value V existed cannot legitimately cite V, so stripping V+ at the tail has zero false positives against real citations ("see m00042" survives; mid-line future refs like "between m00056 and m00999" also survive).
- The `text.complete` handler (`lib/hooks.ts`) applies this after the existing tag stripping via a synchronous registry lookup; when session state is unavailable (eviction, internal sessions) it falls back to today's tag-only behavior. O(text) per completion.
- Known limitation (documented): echoes of **already-assigned** refs are not covered — deliberate, since those may be legitimate citations.
- +222-line regression suite (`tests/leaked-trailing-ref.test.ts`), plus review-nit coverage (mixed below/future-bound sequences, non-integer bound guards, b0 exclusion, 4-digit m-refs) and a cast-free bounds-narrowing refactor.

**2. Windows path protection actually works now** (#403, fixes #402):
`normalizePath()` searched for a **two**-character string (source literal `"\\\\"`) instead of a single backslash, so real Windows paths were never normalized and `protectedFilePatterns` silently failed to protect them — a no-op on the one platform that needs it. Now `replaceAll("\\", "/")`. Ported from upstream DCP commit 5f8f33b; +104 tests (5 of 8 fail against pre-fix code).

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

### v1.18.1 — paper preprint v0.2 into the repo (docs only)

**PR #394.** No runtime code changes — this release ships ACP's research preprint and its figures into the repository, linked from both READMEs.
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# 更新日志

### v1.18.2 — 剥离助手文本尾部泄漏的裸 ACP 引用 + 修复 Windows 路径保护静默失效

**PR #432 + PR #403。** 捆绑两个 bug 修复 —— 无配置或状态格式变更。

**1. 泄漏裸引用剥离**(#432,修复 #431):
模型偶尔在生成末尾退化,回显最后一条可见消息上看到的 `<dcp-message-id>` 标注模式,在完成文本尾部留下**裸引用 + 垃圾**片段(如 `m00057 <随机多语言文本>`)。旧 sanitizer 只剥离完整/不完整的 *标签*,这些无标签片段因此漏过、被持久化进 OpenCode DB,并重新进入后续上下文与压缩摘要。
- 新纯函数 `stripLeakedTrailingRefs(text, { nextMessageRef, nextBlockRef })`(`lib/messages/utils.ts`):单次正则扫描**行首**裸引用(`m\d{4,5}`、`b[1-9]\d*`);首个数值 ≥ 待分配边界(`messageIds.nextRef` / `prune.messages.nextBlockId`)的匹配触发从该处到文末的截断(尾随空白修剪)。
- 为何只剥"未来引用"是安全的:引用严格单调递增 —— 在数值 V 存在之前产生的输出不可能合法引用 V,对真实引用零误伤("see m00042" 保留;行中未来引用如 "between m00056 and m00999" 也保留)。
- `text.complete` handler(`lib/hooks.ts`)在既有标签剥离之后经同步 registry 查找应用;会话状态不可用时(驱逐、内部会话)→ 回退到纯标签行为。每次完成 O(text)。
- 已知限制(已文档化):**已分配**引用的回显不在覆盖范围 —— 有意为之,那些可能是合法引用。
- +222 行回归测试(`tests/leaked-trailing-ref.test.ts`),另加评审补测(混合 below/future 边界序列、非整数边界守卫、b0 排除、4 位 m 引用)与无 cast 边界收窄重构。

**2. Windows 路径保护真正生效**(#403,修复 #402):
`normalizePath()` 搜索的是**两字符**字符串(源码字面量 `"\\\\"`)而非单个反斜杠,真实 Windows 路径从未被归一化,`protectedFilePatterns` 在其唯一需要的平台上静默失效(no-op)。现改为 `replaceAll("\\", "/")`。移植自上游 DCP 提交 5f8f33b;+104 行测试(其中 5 个在修复前代码上失败)。

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

### v1.18.1 — 论文预印本 v0.2 入库(纯文档)

**PR #394。** 无运行时代码变更 —— 本次发布将 ACP 的研究预印本及其配图收入仓库,并在两个 README 中加链接。
Expand Down
37 changes: 37 additions & 0 deletions devlog/2026-09-19_release-v1.18.2/REQ.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# REQ - Release v1.18.2 (patch)

- Task ID: `2026-09-19_release-v1.18.2`
- Home Repo: `opencode-acp`
- Created: 2026-09-19
- Status: InProgress
- Priority: P1
- Owner: ranxianglei
- References: https://github.com/ranxianglei/opencode-acp/issues/400 (floor 12, "发新版本")

## Scope

Bump `package.json` 1.18.1 → 1.18.2 and ship everything merged to master since v1.18.1:

| PR / commit | Content | Issue |
|-------------|---------|-------|
| #432 | Strip leaked bare ACP refs from completed assistant text — new pure function `stripLeakedTrailingRefs()` in `lib/messages/utils.ts`, applied by the `text.complete` handler in `lib/hooks.ts`; +222-line test suite `tests/leaked-trailing-ref.test.ts`, review-nit tests, cast-free bounds-narrowing refactor | fixes #431 |
| #403 | Normalize single Windows path separators in `protectedFilePatterns` (`lib/protected-patterns.ts` one-character fix; +104 tests) | fixes #402 |
| c6066c4b (CI) | `.github/workflows/publish-stable-from-acp.yml` — publishes the separate `opencode-stable` CLI fork; CI-only, no runtime code | — |
| #433 | promote-stable devlog only (side effect already executed: npm `stable` = 1.18.1) | — |

Both runtime changes are bug fixes → semver PATCH: **v1.18.2**.

## Changes in this branch

1. `package.json`: `version` 1.18.1 → 1.18.2
2. `CHANGELOG.md`: new `### v1.18.2` entry at top
3. `CHANGELOG.zh-CN.md`: new `### v1.18.2` entry at top
4. This devlog folder (`REQ.md` + `WORKLOG.md`)

No other code changes. Branch name `YYYY-MM-DD_release-v{VERSION}` + human merge triggers `release.yml`: auto-tag `v1.18.2` → build → test → npm publish to `latest` → GitHub Release.

## Verification plan

- `./scripts/ci/check-pr.sh 2026-09-19_release-v1.18.2 origin/master` (changelog check active this time because version changed)
- `npm run typecheck`, `npm run build`, `npm run test`
- After human merge: verify `npm view opencode-acp dist-tags.latest` = 1.18.2 and the GitHub Release exists.
25 changes: 25 additions & 0 deletions devlog/2026-09-19_release-v1.18.2/WORKLOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# WORKLOG - Release v1.18.2

## Steps

1. Branched `2026-09-19_release-v1.18.2` from `origin/master` (`026dbe73`, includes merges of #432 + #433).
2. Bumped `package.json` version 1.18.1 → 1.18.2.
3. Added `### v1.18.2` entries at the top of `CHANGELOG.md` + `CHANGELOG.zh-CN.md`.
4. Created this devlog folder (`REQ.md` + `WORKLOG.md`).
5. Local verification (below).
6. Pushed branch + opened release PR (references issue #400 floor 12; does **not** close #400 — long-lived release issue).

## Local verification (2026-09-19)

| Check | Result |
|-------|--------|
| `./scripts/ci/check-pr.sh 2026-09-19_release-v1.18.2 origin/master` | branch name ✓, devlog REQ/WORKLOG ✓, changelog `### v1.18.2` present in both files ✓ |
| `npm run typecheck` | clean |
| `npm run build` | success — `dist/index.js` 484.35 KB |
| `npm test` | **1290/1292** — 2 failures are sandbox-only (hardcoded `/tmp` paths vs this workdir's read-only `/tmp` mount): `tests/soft-block.test.ts` and E2E "toFile on inactive block writes block summary". Pre-existing on master; GitHub CI runners unaffected (PR #433's full CI matrix was green with the same suite). |

## Post-merge (human merge + automated CI)

- Human merges the PR → `release.yml` detects release branch → tags `v1.18.2` → `npm ci` → `check:package` → full test → publishes to npm `latest` → creates GitHub Release.
- Verify after publish: `npm view opencode-acp dist-tags.latest` = 1.18.2; `gh release view v1.18.2`.
- Note: npm `stable` stays at 1.18.1 until a future promote-stable request.
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.18.1",
"version": "1.18.2",
"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