diff --git a/README.en.md b/README.en.md index bad5be1..13a5fdc 100644 --- a/README.en.md +++ b/README.en.md @@ -3,7 +3,7 @@ [English](./README.en.md) | [中文](./README.md) > **⚠️ Beta notice — not for production use** -> This project (**v0.2.21**) is a work-in-progress beta. The [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) itself is also in **public beta**. **Do not use either in engineering / production environments** — expect breaking changes and rough edges. +> This project (**v0.2.22**) is a work-in-progress beta. The [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) itself is also in **public beta**. **Do not use either in engineering / production environments** — expect breaking changes and rough edges.

Built with gratitude on top of these projects — please give them a ⭐: @@ -100,7 +100,7 @@ This only installs the package into your project/global store; it does **not** t **Install from the git source (`github:` spec — the form the plugin store shows).** The prebuilt `dist/` artifacts are committed to this repository, so a git-source install also works out of the box — **no build step needed**, and pnpm 11's default build-script blocking (`allowBuilds`) never applies to this package: ```bash -dsh plugin --profile web add github:Tyan66666/billion-context-dsh#v0.2.21 +dsh plugin --profile web add github:Tyan66666/billion-context-dsh#v0.2.22 ``` Prefer a `#` ref to get artifacts identical to that npm release; without a ref you get the latest default-branch build. Only building the repo yourself (`npm run build`) requires approving build scripts. Background and trade-offs: [docs/git-source-install-design.md](docs/git-source-install-design.md) (issue #92). diff --git a/README.md b/README.md index 2093439..aa8eda6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [中文](./README.md) | [English](./README.en.md) > **⚠️ 测试版声明——请勿用于生产环境** -> 本项目(**v0.2.21**)仍处于开发中的测试版。[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 本身也处于**公开测试版**阶段。**请勿将两者用于工程化 / 生产环境**——预期会有破坏性变更与粗糙之处。 +> 本项目(**v0.2.22**)仍处于开发中的测试版。[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 本身也处于**公开测试版**阶段。**请勿将两者用于工程化 / 生产环境**——预期会有破坏性变更与粗糙之处。

衷心感谢以下项目——请给它们一个 ⭐: @@ -99,7 +99,7 @@ npm install billion-context-dsh **git 源安装(`github:` 规格,插件商店展示的形态)。** 预构建产物 `dist/` 已提交到仓库,从 git 源安装同样开箱即用——**无需任何构建步骤**,pnpm 11 默认拦截构建脚本(`allowBuilds`)的机制对这个包不构成障碍: ```bash -dsh plugin --profile web add github:Tyan66666/billion-context-dsh#v0.2.21 +dsh plugin --profile web add github:Tyan66666/billion-context-dsh#v0.2.22 ``` 建议带 `#` 安装,拿到与对应 npm 版本完全一致的产物;不带 ref 则装默认分支的最新构建。只有 clone 仓库自行从源码构建(`npm run build`)才需要放行构建。背景与方案取舍见 [docs/git-source-install-design.md](docs/git-source-install-design.md)(issue #92)。 diff --git a/docs/README.md b/docs/README.md index b5f9918..5475553 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,7 @@ [English](./README.md) · [简体中文](../README.md) · [项目主页](https://github.com/Tyan66666/billion-context-dsh) -> **⚠️ Beta** — this project (v0.2.21) and the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) are both in **public beta**: do not use in engineering / production environments. +> **⚠️ Beta** — this project (v0.2.22) and the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) are both in **public beta**: do not use in engineering / production environments. Model-driven context management (Active Context Pruning / ACP) for the DeepSeek Harness, ported from [billion-context-pi](https://github.com/ranxianglei/billion-context-pi). The compression core ([acp-kernel](https://github.com/ranxianglei/acp-kernel)) is reused verbatim. @@ -20,6 +20,7 @@ Model-driven context management (Active Context Pruning / ACP) for the DeepSeek | [Runtime settings integration design](settings-integration-design.md) | Phase-1 settings seam (issue #75): the six scalar knobs hot-editable via `~/.dsh/settings.yaml` / `/acp config`, layering (schema default → composition row → user section), base-filtering rationale, window-cache invalidation, kill switch, /acp config parse rules | | [E2E host harness design](e2e-harness-design.md) | Why the host-integration regression suite (`scripts/e2e/`) assembles the real DSH agent loop in-process against a scripted fake LLM (issue #120); scenario schema, the honest-usage projection-anchor trap, the rc.6 peer-closure pin, phase-2 notes | | [Injection governance design](injection-governance-design.md) | Why model-written summaries get a source frame written once at creation (B1), why unchanged-injection elision (B2) was dropped (host evidence: no visible-time re-injection; the stub would steal #93's newest-row pin; the whitelist matched ≤1 real frame kind), how verifiedReadings ride the rawOutput ledger yet stay readable (B3), and why nudge bodies stay slim (B6) | +| [Media visibility design](media-visibility-design.md) | Why image/file blocks must stay visible to the engine (issue #117): the deterministic placeholder projection, the host-meter media price, the range-row marker, the rejected alternatives, and the mutation-verified tests | ## 🗂 Source layout @@ -40,40 +41,9 @@ src/ └── commands.ts # M4: /acp slash command ``` -## 📦 Releases| [Media visibility design](media-visibility-design.md) | Why image/file blocks must stay visible to the engine (issue #117): the deterministic placeholder projection, the host-meter media price, the range-row marker, the rejected alternatives, and the mutation-verified tests | +## 📦 Releases -- [v0.2.21](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.21) — (fix) **two live-session killers: shadow-price claims overstate image sessions (projection goes negative, every turn fails) and every compress crashes on DSH 0.1.2 hosts** (#103, #124): ① On sessions containing image messages, the shadow-price claim read the token-meter's route-repriced `node.tokens` instead of the fixed heuristic — under an image route's declared visual price the claim overstated the shadowed range, the projection ledger folded `messageTokens` negative, and the zod nonnegative gate rejected every subsequent turn until the cache was zeroed by hand (issue #103, host 0.1.2-rc.1 screenshot session). Fix: `shadowedTokensViaMeter` (`src/host-tokens.ts`) now prices claims with `node.heuristicTokens ?? node.tokens` — the fixed-heuristic basis the projection ledger itself accumulates with (`heuristicTokens` exists since 0.1.2-alpha.2; on older meters the single `tokens` field IS the fixed heuristic, so both shapes are covered). 🙏 Thanks to **[@alonewinds](https://github.com/alonewinds)** for the report and the verified root cause. ② dsh-session 0.1.2-rc.1 removed the `session.events` getter while `@deepseek-ai/dsh-compaction`'s `toolPairingBalancedBefore/After` still read it — after the host upgrade every compress threw `Cannot read properties of undefined (reading '8')` (issue #124; the host's own compaction-basic hits the same code). Fix: `src/tool-pairing.ts` mirrors the host's pairing-balance cache line for line and reads events through the cross-version accessor, with an `UPSTREAM:` removal gate to restore the host helpers once the host fix ships. **214 tests pass** (2 new image-route shadow-price regressions incl. a pre-0.1.2 single-field shape test; 4 new tool-pairing tests incl. a 0.1.2-shape stub E2E); live-verified on DSH 0.1.2-rc.1: after the upgrade two large compressions + two prunes succeeded, claims matched the fixed-heuristic mirror sums exactly (60,667 and 57,733 tokens), and the projection ledger stayed non-negative (+5,632). -- [v0.2.21](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.21) — (fix) **pressure decisions now run against the sustainable input budget — window minus the per-request output reservation — not the raw window** (#106, 🙏 thanks to **[@wszhoho](https://github.com/wszhoho)**): every provider reserves the adapter's per-request output cap (`defaultMaxTokens`) at the end of the window on each request, so a 96K window with a 16K cap carries at most 80K of input — the raw denominator understated usage by cap/window (≈17% there, and far worse on short-window models, where the same cap is a quarter or more of the window; the old 85% line plus the 16K output overflowed the 96K window entirely). Fix: `windowFor` (`src/index.ts`) subtracts the cap in one place (`applyReservation`); `probeModelWindow` (`src/window.ts`) returns window + cap from a single `resolveModelInfo` call with the cap cached per route (`outputReservationCache`); the subtraction is skipped for an explicit `modelContextLimit` (the operator owns the denominator), a failed probe (raw 128K fallback preserved), a degenerate cap ≥ window, and `autoModelContextLimit: false`; `AcpWindow` now carries `rawLimit`/`outputReserved` and `/acp status` shows the arithmetic (`context window: 79616 (raw 96000 − 16384 output reservation; auto)`). Docs synced in the same PR: AGENTS.md (module map + design decision 9), README (zh/en) config tables + module maps, docs/INSTALL.md config comments, new docs/output-reservation-design.md. **208 tests pass** (seven new window tests: single-probe shape; undisclosed/failing/missing probes → nulls; auto-path subtraction; projection-path subtraction with per-route cap cache; no-cap no-op; degenerate cap ≥ window; explicit config never probes or subtracts). -- [v0.2.19](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.19) — (fix) **a crash mid-compression no longer permanently blocks every later `compress` call** (#98): `runCompactionTransaction` writes `compaction/start`, then `compaction/summary`, then the `user/message` surface replacement, then `compaction/end`; if anything throws between `start` and `end` (live case: re-compressing a span already gone from the surface — `surface replace: start seq N not found in surface`), the `start` is left in the durable log without an `end`, and from then on every `compress` call fails with `billion-context-dsh: another compaction is already active for this session` — even across restarts, with no reset path. Fix, three parts: ① `assertNoActiveCompaction` treats a dangling `compaction/start` (no matching `compaction/end`) as stale and warns `billion-context-dsh: clearing stale compaction flag — found a compaction/start with no matching compaction/end` instead of throwing, so the session self-heals; ② `runCompactionTransaction` validates the range **before any event is written** — a reversed or not-in-surface range throws with zero durable events, so a bad call never leaves an orphan summary; ③ the writes after `compaction/start` are wrapped in a try/catch that appends a compensating `compaction/end` before rethrowing, so a mid-write throw is always paired. **201 tests pass** (three new: a stale dangling start self-heals; a failed transaction writes a compensating `compaction/end`; an out-of-surface range fails fast with zero events written); live-verified on DSH 0.1.2-alpha.5 — repeating a `compress` throws `surface replace` but the last durable event is `compaction/end`. -- [v0.2.18](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.18) — (fix) **the `compress` tool no longer crashes on DeepSeek Harness 0.1.2-alpha.x** (#96): on DSH 0.1.2-alpha.5 the host session dropped the `events` array (removed in alpha.4+), so the seam's session→event lookup read `undefined[7]` and threw `Cannot read properties of undefined (reading '7')` on the real `compress` path. Fix: the seam contract now uses the cross-version accessor `session.eventAt(seq)` (present on alpha.x) instead of the removed `session.events[seq]`. Same PR also fixes an incomplete peer contract — `dist/index.js` VALUE-imports four `@deepseek-ai` seam packages (`dsh-compaction`, `dsh-llm`, `dsh-session`, `dsh-tools`) but only `dsh-compaction` was declared as a peer, so a non-hoisted/stale-nested install could resolve the others to a copy inconsistent with the host; all four now share the peer range `^0.1.0-rc.6 || ^0.1.1-rc.1 || ^0.1.2-alpha.4` (the next-minor line `0.1.3`/`0.2.x` stays rejected per issue #68 — not yet published, API unverifiable). README (zh/en), INSTALL.md, and the peer-range tests (which now loop every seam peer) were updated. **199 tests pass**; live-verified on DSH 0.1.2-alpha.5: a real `compress` runs `toolPairingBalancedBefore/After` (the exact crash site) and returns a tier-1 block with no `reading '7'` error. 🙏 Thanks to **[@wszhoho](https://github.com/wszhoho)** for the root-cause analysis and the cross-version fix (`src/session-events.ts`, migrating 40 `session.events` accesses; peer range covering the rc.6 / 0.1.1-rc / 0.1.2-alpha lines). -- [v0.2.17](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.17) — (fix) **git-source installs work again — prebuilt `dist/` is committed to the repo, with a zero-build-script contract and a CI drift guard** (#92, #94): a `github:` install (the form the plugin store shows) cloned a tree with no `dist/` while package.json's `main`/`types`/`exports` all point there — the import failed immediately; and the two obvious workarounds are both dead ends on modern pnpm: a `prepare` script never runs because pnpm ≥10/11 blocks dependency build scripts by default, and a git-hosted package's `prepare` is gated behind an `allowBuilds` key that must contain the full depPath including the exact commit hash ([pnpm#12367](https://github.com/pnpm/pnpm/issues/12367)) — its mere presence hard-fails the install (`ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED`). Fix: commit the 14 built `dist/` files (byte-identical with the npm tarball — rebuilds are deterministic, toolchain lockfile-pinned), add the zero-build-script contract guarded by `tests/package-artifacts.test.ts` (artifacts exist and are non-empty; the bundle carries `AcpCompactionEngine`; `prepare`/`preinstall`/`install`/`postinstall` are banned), and a CI step that rebuilds and fails when the committed `dist/` drifts from source. README (zh/en) + INSTALL.md gain a git-source install section (Method D), the decision record lives in `docs/git-source-install-design.md`, and AGENTS.md §5 records the dist-committed convention (every `src/` PR rebuilds and commits `dist/`; never add build lifecycle scripts). **189 tests pass**; verified end-to-end on a clean directory with pnpm 10.30.3 and 11.25.0 installing from the branch. -- [v0.2.16](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.16) — (fix) **context window now follows the session's real route — mid-session model switches no longer fire false ~300% EMERGENCY nudges** (#89): `windowFor`'s auto-detection probed `agent.options.provider/model`, a snapshot taken at session start — after switching a session from a 96K-window model to a 1M-window model mid-session it still probed the OLD route, read the session as 96K, and reported ~300% usage (every nudge fired EMERGENCY while the model's own context breakdown showed ~28%, so it correctly refused to compress — the nudge mechanism was completely defeated). Fix: the window resolution chain now reads the host session projection FIRST (`sessionProjections.contextPressure.contextWindow` — `src/window.ts` `projectedContextWindow`, disclosed per-request for the CURRENT route) and falls back to the `llm.resolveModelInfo` probe only when the projection discloses no window; the projection value is deliberately NOT cached in `windowCache` (caching would freeze the pre-switch window for the whole process lifetime — the same false-alarm trap as the probe-failure cache); explicit `modelContextLimit` still wins, and `autoModelContextLimit: false` skips BOTH the projection and the probe (now pinned by a dedicated test — the gate previously had no test coverage). Review follow-ups shipped in the same PR: README.en.md config-table row synced to the projection-first order, module-map/docstring/comment refresh (AGENTS.md, README.md/README.en.md, `src/index.ts` `AcpConfig` docstrings, `src/window.ts`), and docs/acp-status-align-design.md now records the one-request last-wins lag (right after a switch the projection still reports the old window until the next request lands). **186 tests pass**; live-verified on DSH web: after a model switch `/acp status` shows `context window: 1000000 (session projection current route...)` and usage returns to ~28% instead of ~300%. 🙏 Thanks to **[@wszhoho](https://github.com/wszhoho)** for the PR and for enabling maintainer edits so the review fixes could land directly on the branch. -- [v0.2.15](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.15) — (feat) **anti-over-compression prompt guidance ships in the default templates** (#55, #85): in review/audit/verification tasks the model compressed source reads it still needed, then had to decompress them back — a compress → decompress → re-compress loop that wasted round-trips and re-grew context. Three guidance lines, proven over an extended live period via a local `config.prompts` override (the same promote-after-local-verification path as the issue #43 copy in v0.2.8), are now the shipped defaults: (1) WHEN NOT TO COMPRESS gains the cite-verbatim bullet — in review/audit/verification tasks keep source reads un-compressed until the final report is written; decompress costs a full round-trip, prefer delaying the compress; (2) the compress description's subtask-completion trigger gains the qualifier "whose details you have fully consumed and will not re-check"; (3) the compress description ends with the self-check "Before compressing, ask: will I need to re-verify any detail from this range in this task? If yes, keep it live." New prompts test #5d pins the three carriers; byte-snapshot test #5 and the WHEN-NOT assertion in test #1 updated; `docs/configurable-prompts-design.md` v7 (revision R6) notes the local override is now redundant and can be removed. **180 tests pass**. -- [v0.2.14](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.14) — (fix) **compress schema gate: `startSeq`/`endSeq`/`summary` required on content items, enforced on BOTH call forms** (#80): a live session showed the model omitting `summary` pass the old no-`required` items schema and loop on the kernel's field-less "Summary is empty"; a topic-only call crashed later with `invalid seq "undefined"`. The schema gate now rejects both with `missing required property "content[0].summary"`. Because the gate only sees TOP-LEVEL arguments, a wrapped call (`{ arguments: { content: [...] } }`) still bypassed it — `handleCompress` therefore re-runs the same per-item check on the unwrapped content (`validateContentItems`, throwing the host's `ToolArgsError` so both forms share one error surface) and treats an empty/whitespace-only summary as missing; top-level `content` stays optional so the envelope can still be unwrapped. 4 regression tests (direct topic-only rejection naming all three fields; wrapped-form missing/whitespace summary; wrapped OBJECT form with a full entry still compresses; `content: []` benign no-op); AGENTS.md rule 9 + §4b synced. **179 tests pass**; live-verified on a local DSH install running this build: every malformed form (direct missing-summary, topic-only, wrapped missing-summary) is rejected at the gate with the field-naming error, and a real compress lands cleanly (16.2K tokens reclaimed, session healthy after the shadow-price fold). 🙏 Thanks to **[@wszhoho](https://github.com/wszhoho)** for the fix and the red/green repro in the PR description. -- [v0.2.13](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.13) — (fix) **`coreOverrides.nudge` reaches the kernel — user growth tuning works again** (#72): the engine always ships explicit pct defaults (`nudgeMaxContextLimitPct: 0.7` / `nudgeEmergencyThresholdPct: 0.85` in `DEFAULT_CONFIG`), so the pct patch was never empty and `kernelConfigFor`'s plain replace (`overrides.nudge = { ...defaults, ...nudgePatch }`) silently discarded every user `coreOverrides.nudge` key (growthFloor/growthCap/minGrowthFloor/…) — the documented escape hatch was dead whenever the pct knobs were set. Fix: three-layer merge with the user section spread LAST (`...defaultConfig(limit).nudge, ...nudgePatch, ...input.coreOverrides?.nudge`); the new user-visible semantics are documented in both READMEs — a same-name key in `coreOverrides.nudge` outranks both the kernel defaults and the top-level pct knobs. Regression suite `tests/config-overrides.test.ts` (wins-over-defaults, same-key conflict that pins the merge order, coreOverrides-only branch, no-coreOverrides unchanged) plus a wiring guard in `tests/mount-probe.test.ts` (the engine now exposes `readonly env`, so a dropped `coreOverrides` forwarding line fails loudly instead of reviving the bug silently). **174 tests pass**; live-verified on DSH web (kimi-k3, 1M window): `growthFloor 300000, growthCap 300000, minGrowthFloor 150000` previously read `threshold 50000; floor 22500`, after the fix reads `threshold 300000; floor 150000`. 🙏 Thanks to **[@wenxb](https://github.com/wenxb)** for the report and the PR. -- [v0.2.12](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.12) — (fix) **install on the latest DSH works out of the box** (#68, #69): the peer range is now `"@deepseek-ai/dsh-compaction": "^0.1.0-rc.6 || ^0.1.1-rc.1"` — npm's prerelease matching only lets a version satisfy a range that carries a comparator on the SAME `[major, minor, patch]` tuple, so the old lone `^0.1.0-rc.6` could never match `0.1.1-rc.x` and npm 12 ERESOLVEd on DSH 0.1.1-rc.2 even though the seam's API never changed (verified version-by-version with real node-semver; boundary guarded by `tests/peer-range.test.ts` — same-line future rcs stay installable, next-minor lines stay rejected). And a store/`dsh plugin` install is now **zero-config global**: the bundle patch also disables the host root-realm `compaction-basic` (only one provider per realm may own `ctx.compaction`; redundant on web where DSH already ships it, the only guard on headless/tui), README (zh/en) + INSTALL.md rewritten so the manual composition rows are only the plain-npm path and config customization (a same-id row overrides the bundle defaults — verified against the real loader via `dsh --dump-config`), AGENTS.md gains design decision 8, contract guarded by `tests/bundle-patch.test.ts`. **169 tests pass**. -- [v0.2.11](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.11) — (fix) **context-window auto-detection now reaches the tools — false pressure alarms gone** (#63, #64, #65): the `compress`/`acp_status` model tools used the 128,000-token fallback constant for every pressure decision while the nudge path used the probed window — on a 1M-window model the tool-side `usage` read ~8× too high (e.g. 39% instead of 5%), and a gateway that discloses no window silently read as "55% of 128K" and triggered false EMERGENCY nudges. Fix: `handleCompress`/`handleStatus` and the human `/acp` panel now share one `resolveEffectiveWindow` (`src/tools.ts`) and feed the probed window into the kernel config (`kernelConfigFor({ ...env, modelContextLimit: window.limit })`) — the `/acp` panel already showed the probed window, the tools now decide on the same one (window rows stay out of the model tool per rule 9). The failure of the probe itself is now surfaced, not hidden: `windowFor` writes a host-log `warn` and marks the window `probeFailed: true` (failures are cached for the process lifetime, so the message says `restart to re-probe`), and `/acp status` appends a ⚠ line after the `context window:` row — explicit config, a successful probe, and disabled auto-detection all stay silent. **165 tests pass**; live-verified on DSH web: a gateway with no model window read `context window: 128000 (default (auto-detection failed — restart to re-probe))` with the ⚠ hint, and a probed 1M window showed `auto-detected from …` with no hint. 🙏 Thanks to **[@adamqeqj003-dotcom](https://github.com/adamqeqj003-dotcom)** for filing issue #63 with a precise root-cause analysis and a concrete fix sketch, and to **[@Jstn-1g](https://github.com/Jstn-1g)** (Justin Skowyra) for PR #64 — the original window-in-tools fix this release builds on (this repo's own #65 then added the probe-failure observability on top). -- [v0.2.10](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.10) — (feat) **make T2/T3 distillation reachable** (#60, #61): the model's only route to tier-2/3 distillation is compressing a LIVE checkpoint seq, but nothing told it which seq that was — the nudge tier line listed discrete seqs without a callable form, acp_status showed only kernel refs (bN), and a distill the range solver degraded to a plain fold reported no tier (a silent downgrade). The nudge tier template gains `{firstSeq}`/`{lastSeq}` slots and now renders a ready-made `compress({ content: [{ startSeq, endSeq, summary }] })` call over the sorted checkpoint seqs; acp_status (overview) appends a `Checkpoint seqs` row mapping each ACTIVE block's kernel ref to its checkpoint summary seq (`blockRegistry` — engine-side wiring, the kernel report is never rewritten); every compress result reports its tier (`, tier N`, tier 1 included). Regression tests: nudge tier seqs first..last compress straight into a tier-2 block end-to-end; plain tier-1 compress reports its tier; the Checkpoint seqs row appears in overview and stays out of drilldown. **162 tests pass**; live-verified on DSH web: the Checkpoint seqs row lists 39 active blocks, a real T2 distillation lands (`block … tier 2`), and a plain compress reports `tier 1` with the adjusted-edge note. -- [v0.2.9](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.9) — (fix) **shadow prices speak the host token vocabulary — CJK sessions no longer brick** (#54): `compaction/summary`/`compaction/prune` `shadowedTokenCount` claims were priced with the CJK-aware `defaultCountTokens` while the host token-meter accounts in flat-4 — on CJK-heavy sessions the meter's `messageTokens` went negative and the projection schema rejected every turn (live session session-3aa366c3: 42,076 accumulated vs 74,858 claimed → ≈ −31K, permanently bricked). New `src/host-tokens.ts` prices claims via `ctx.tokenMeter.measure(session)` node prices (exact by construction, follows host estimator changes) with an exact mirror fallback (NEVER `defaultCountTokens`); all three event writers fixed (handleCompress / hideSurfaceSeqs / `/acp compress`), plus the `/acp compress` raw-vs-resolved crash (shadowedSeqsOf now uses the RESOLVED edges — adjusted ranges previously threw in assertProvenance). Regression suite `tests/shadow-price.test.ts` drives a REAL TokenMeter + SessionProjectionRegistry over CJK fixtures (claim == meter price, projection non-negative, prune host pricing, mirror edge cases). `scripts/rescue-shadow-price.mjs` rescues overclaimed sessions (multi-frame zstd, node:zlib, header frame + events frame). **160 tests pass**; live-verified on DSH web: a fresh CJK-heavy session compressed twice (claim 26,712 == 26,712; prune 543 == 543), host projection +27,055 (min +182), zero turn errors. -- [v0.2.8](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.8) — (feat) ship issue #43 in the **default** compress tool description: semantic compression timing ("stage or subtask completion, strategy switches, intermediate milestones, wrapping up failed exploration — when the details are consumed") + actionable summaries ("turn dead-end exploration into a conclusion (what was tried, why it failed, the next step) — not a blow-by-blow; keep the summary the ONLY record, self-contained") — previously local-only patch config (cordis.patch.yml), now the built-in default template with the local override removed; prompts test #5b pins the three semantic carriers (`/acp status` previously abandoned this text); configurable-prompts-design.md revision record R5; **154 tests pass** -- [v0.2.7](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.7) — (fix) `/acp status` lists **ALL** compressed blocks instead of only the oldest 10 — `ledger.slice(0, 10)` truncated the human-side panel to the 10 OLDEST blocks (the ledger is ordered by event time), so recent work (e.g. a long-memory design block at position 32 of 33) was invisible and looked lost; the block list is folded in the GUI anyway so length costs nothing, every block is now listed (#47, #48); regression test: 12 non-overlapping compress ranges → 12 blocks, the 11th and 12th block prefixes must appear (the old slice failed this) — **153 tests pass** -- [v0.2.6](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.6) — (feat) `/acp status` shows **nudge arbitration** — the human-side panel now runs the same kernel turn as the nudge path (read-only, on a cloned state, never writes the store) and reports `nudge: idle/ACTIVE [Tn] — reason` plus how many tokens remain until the next nudge (`next nudge: ~N tokens to go (usage X% → Y% line)`, Y = engine 70% nudge line) — aligning `/acp` with billion-context-pi's `Nudge: idle/ACTIVE — reason` panel and answering "how far from the next nudge"; 4 new `/acp` regression tests (idle arbitration + distance, ACTIVE arbitration, ledger listing, dual-id bN/prefix decompress) — **152 tests pass** -- [v0.2.5](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.5) — (chore) bump acp-kernel 0.0.24 → 0.0.29, now **truly inlined** via `tsup noExternal` (the package moves to devDependencies; the release artifact carries zero runtime deps and zero `from "acp-kernel"` imports — previously the docs' inline claim did not match the build, the published bundle had 8 external `acp-kernel` imports); kernel 0.0.29 adds `Intl.Segmenter('zh')` single-pass CJK tokenization with all-OOV bigram+unigram fallback, fuzzy query gate `length>=4` or (`length>=2` && CJK) — 2-char CJK terms (缓存/登录) now enter the recall path, per-doc feature memoization (`docFeatures`, 8MB LRU cap), `tokenSnapshot` in `CompressionState`, real-character-count range merging; (feat) `compress` accepts drilldown mN refs (#35): mN boundaries reverse-map to live surface seqs via the current turn's `state.messageRefs.byRef` (unknown mN fails with guidance, store-state lookup never used — acp_status's turn is not persisted); (feat) nudge range table gains a kernel-parity tool/text share `[tool X% | text Y%]` and orders ranges oldest-first (stable across turns); (fix) `preserveRecent: 0` no longer protects everything (`slice(-0) === slice(0)`); (docs) design decision 7 + rule 11 "Kernel defects are fixed UPSTREAM, never patched locally" — `buildCompressibleSeqRanges` is now a labeled `UPSTREAM:` workaround tracked in docs/dsh-porting-verification.md and issue #38 (kernel ref-map drift after surface replacements; drop the workaround once upstream fixes the drift); (test) 36 vendored upstream acp-kernel search tests migrate to the public API (`tests/kernel-upstream/`, issue #30, PR #37) — **148 tests pass**; live-verified on DSH web: 2-char CJK query 审阅 hits the compressed block (score 1.00), `tokenSnapshot` search returns shadowed originals with back-links, decompress restores the full block text -- [v0.2.4](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.4) — (feat) `search_context` switches from hand-rolled substring counting to the pinned acp-kernel 0.0.24 `searchBlocks` hybrid retrieval (#23): BM25 stemmed + CJK bigram + character n-gram fuzzy, role-weighted (user×1.5/assistant×1.0/tool×0.6); `buildSearchDocs(session)` rebuilds a unified doc set from the log — one block doc per ledger entry (text = summary, ref = compactionId, `decompress` closes the loop) plus message docs from `expandShadowedSeqs` (incl. tier-2/3 distillation expansion), each seq claimed by its earliest/innermost covering block (pi owner-map alignment); hits render `block ` or `message seq N (role, in block )` with the score surfaced — **trusts the kernel, no engine-side gate**: an early BM25 no-match gate was removed after it killed 6/46 real kernel-bench queries (stemming/fuzzy matches hybrid would have found), scores pass through for the model to judge weak hits (fuzzy-only ≈0.3 ceiling on noise; verified on kernel CORPUS 46 queries: gate R@1=36/46 vs no-gate 38/46, R@3=41/46); 4 search regression tests (stemmed rate-limit, CJK rate-limiting, shadowed-message hit with block back-link, tier-2-distilled innermost tier-1 block back-link); `quantum teleportation` assertion now compares scores instead of asserting `no matches`; AGENTS.md §2 design decision 6 "Search trusts the kernel"; live-verified on DSH web: search hits across two compressed blocks with back-links, decompress recovers 129 messages, compress writes a new block (search→decompress→compress loop closes); 108 tests pass; full investigation archive in issue #32 -- [v0.2.3](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.3) — (feat) align the model tool `acp_status` with upstream billion-context-pi: it now renders through the kernel's `buildStatusReport` — CONTEXT BREAKDOWN (tool/text/summaries token shares of the visible total, no window semantics), COMPRESSED BLOCKS ledger, and the kernel nudge decision line — and drops the engine-side `estimated context` / `context window` rows (window info stays in the human `/acp` command); checkpoint summary nodes are excluded from the breakdown so summaries are never double-counted; `surfaceSummary` reports the span as min..max (a compaction replace lands the checkpoint node first, which previously read "seqs 15..12"); (feat) `decompress` accepts the kernel block ref `bN` that acp_status shows (dual id space: exact `bN` first, compaction-id prefix fallback; `/acp decompress` too) so the block rows are directly usable by the model; (feat) `acp_status` supports scoop-driven drilldown — `scope:"compressed"` per-block list, `scope:"uncompressed"` + `view:"messages"`/`"ranges"` per-message/per-range listing, with `tool` filter, `sort` (size/time/tool/age) and `limit` cap, all passed through verbatim to kernel `buildStatusReport` (no args stays the overview); a drilldown request omits the nudge decision line (upstream mirror) but keeps the `Surface:` seq anchor; drilldown rows carry kernel refs (mN) that are labelled size-awareness-only — an explicit `Note:` line separates them from the compressible Surface seqs, with mN→seq adaptation slated for when the search_context seq dialect lands (#23); (fix) prompt copy makes the split explicit — compress boundaries are SURFACE SEQS, not the `bN` refs (which are for decompress); + (fix) tool/result projection backfills `toolName`/`toolCallId` from an assistant tool-call index (`buildToolCallIndex`, keyed by the shared `toolCallIdOfResultEvent`) — real DSH tool-result events carry no `message.toolName` (identity lives in `message.source.callId` / the nested `tool-result` block), so previously every tool output landed in an empty-named bucket and `acp_status` rendered `Top tools: (62%)` with a `tool:""` kernel Tip; the extractor is now a single shared implementation with `region.ts`'s call/result pairing; + (fix) the model channel may wrap ANY tool's args under `{ arguments: {…} }` — a live drilldown call arrived as `{"arguments":{"scope":"compressed"}}` and was SILENTLY dropped (acp_status is the only all-optional tool, so the envelope passes schema validation; decompress/search_context reject it loudly at the schema gate), all parameterized tools now peel the envelope (`unwrapEnvelope`, object or JSON-string) — with compress's own unwrap retained; + 15 regression tests (105 tests pass, no regression) -- [v0.2.2](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.2) — (fix) hide compress call/result after landing and prune orphan tool messages (#21) — fixes #18 (the nudge compressible-range table collapsed to ~28 tokens): deferred (reentry-safe) compress call/result hiding, single-call hide guard, full in-flight call protection (`openToolCallIds`), broken-pair self-healing for legacy deadlocked sessions, batch compression resilience (a kernel-rejected range no longer poisons the batch), unconditional `agent/pre-step` orphan stripping; 90 tests pass (6 new regressions); live-verified on DSH web (no 400 after compress; real nudge range table) -- [v0.2.1](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.1) — (feat) align nudge and system-prompt copy with acp-kernel/billion-context-pi (#14): default nudges now render through the kernel's `renderNudgeText` — efficiency-note frame ("not an overflow warning"), context breakdown, HOW_TO_COMPRESS_RULES, tier rules (TIER2/3), and batch tip — with only the ref-ID segments adapted to the surface-seq range table; the emergency tier says "compress now"; the system prompt gains WHEN TO COMPRESS / WHEN NOT TO COMPRESS lists and kernel rule placeholders; `config.prompts` overrides keep the template path (custom copy wins); + 3 regression tests (80 tests pass, no regression) -- [v0.2.0](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.0) — (feat) ship a `dsh.bundle` manifest: the package is now installable with `dsh plugin --profile web add billion-context-dsh` (the patch auto-inserts the composition row), which also unlocks listing in the awesome-dsh-plugin registry and the dsh-market plugin store; (chore) add npm keywords for search discoverability; docs: bundle install method in README (zh/en) and INSTALL.md 方式 C; 77 tests pass (no regression) -- [v0.1.9](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.9) — (feat) configurable per-stage prompts via `config.prompts` (nudge frames/range table/system prompt/tool descriptions as validated templates; fail-fast on unknown placeholders), (chore) bump acp-kernel 0.0.23 → 0.0.24 (inline-dependency upgrade), docs: update acp-kernel version reference in AGENTS.md; 77 tests pass (no regression) -- [v0.1.8](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.8) — (fix) system prompt section cold-start retry: the ACP guidance section is now registered even when the `systemPrompt` service activates after the engine — matches the same retry pattern used by tools and commands; (fix) nudge context pressure now reads from `sessionProjections.contextPressure.projectedTokens` (matches the UI context-occupancy display; includes fixed overhead) instead of `tokenMeter.measure(session).surfaceTokens`; docs: INSTALL.md 2a notes that disabling compaction-basic is redundant on dsh 0.1.0-rc.6+; + 3 regression tests (62 tests) -- [v0.1.7](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.7) — (fix) compress no longer fails with *seq not in the current surface* when the model reuses stale refs (old nudge tables / earlier compress results): shadowed edges are remapped to the still-live content of the requested span, a fully shadowed span is reported as *already compressed* with the covering block ids, block checkpoint nodes are never folded on a stale reference (distillation stays explicit), and invented/other-session seqs still fail with acp_status guidance; guidance updated in the system prompt, nudge range table and compress tool description, + 6 regression tests (60 tests) -- [v0.1.6](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.6) — (feat) auto-detect the model context window from the LLM runtime (`agent.ctx.llm.resolveModelInfo`; explicit `modelContextLimit` wins, falls back to the default), (feat) engine nudge thresholds lowered to 0.70/0.85 (forced nudge before the host 80% compaction line; explicit values win), docs: clarify nudge trigger semantics — growth path has no percentage floor, + 3 regression tests (54 tests) -- [v0.1.5](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.5) — (feat) tier-2/3 block distillation: compressing a block's summary node distills it into a higher tier (T1→T2→T3), with recursive decompress, log rehydration of kernel blocks (restart-safe), tier-aware nudge/status, + 8 regression tests (42 tests) -- [v0.1.4](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.4) — (feat) guide the model toward multi-segment batch compression: the nudge range table, system prompt, and the compress tool description now point at batching multiple disjoint ranges in one call (each entry its own block), + regression test (34 tests) -- [v0.1.3](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.3) — compress / resolveSurfaceRange errors now point the model at `acp_status` for the current surface (sparse-node guidance) -- [v0.1.2](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.2) — fix: compress failed with *no assigned ref* when a range edge landed on a multi-tool-call assistant message (balanced plain-ref boundaries, 32 tests) -- [v0.1.1](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.1) — 6 fixes from long-session testing (ledger tokens, CJK-aware estimation, lone tool-result expansion, surface-based range table, …) -- [v0.1.0](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.0) — initial release +完整发布历史(每版的变更记录与致谢)见 [GitHub Releases](https://github.com/Tyan66666/billion-context-dsh/releases) —— 仓库文档不再维护历史镜像,避免与发布页不一致。 ## 🔗 Quick links diff --git a/docs/index.md b/docs/index.md index f8a4b08..b3172b6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ # billion-context-dsh -> **⚠️ Beta notice** — this project (v0.2.21) and the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) are both in **public beta**: do not use in engineering / production environments. +> **⚠️ Beta notice** — this project (v0.2.22) and the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) are both in **public beta**: do not use in engineering / production environments. **Model-driven context management (Active Context Pruning / ACP) for the DeepSeek Harness.** The model decides *when* and *what* to compress — not a hard limit. Ported from [billion-context-pi](https://github.com/ranxianglei/billion-context-pi) (by [ranxianglei](https://github.com/ranxianglei), MIT); the compression core [acp-kernel](https://github.com/ranxianglei/acp-kernel) is reused verbatim. @@ -19,6 +19,6 @@ ## 🔗 Quick links - **Repository**: [github.com/Tyan66666/billion-context-dsh](https://github.com/Tyan66666/billion-context-dsh) -- **npm**: [billion-context-dsh@0.2.21](https://www.npmjs.com/package/billion-context-dsh) -- **Releases**: [v0.2.21](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.21) · [v0.2.19](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.19) · [v0.2.18](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.18) · [v0.2.17](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.17) · [v0.2.16](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.16) · [v0.2.15](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.15) · [v0.2.14](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.14) · [v0.2.13](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.13) · [v0.2.12](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.12) · [v0.2.11](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.11) · [v0.2.10](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.10) · [v0.2.8](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.8) · [v0.2.7](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.7) · [v0.2.5](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.5) · [v0.2.4](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.4) · [v0.2.3](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.3) · [v0.2.2](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.2) · [v0.2.1](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.1) · [v0.2.0](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.2.0) · [v0.1.9](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.9) · [v0.1.8](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.8) · [v0.1.7](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.7) · [v0.1.6](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.6) · [v0.1.5](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.5) · [v0.1.4](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.4) · [v0.1.3](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.3) · [v0.1.2](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.2) · [v0.1.1](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.1) · [v0.1.0](https://github.com/Tyan66666/billion-context-dsh/releases/tag/v0.1.0) +- **npm**: [billion-context-dsh@0.2.22](https://www.npmjs.com/package/billion-context-dsh) +- **Releases**: [GitHub Releases](https://github.com/Tyan66666/billion-context-dsh/releases)(全量历史、变更记录与致谢) - **Upstream**: [billion-context-pi](https://github.com/ranxianglei/billion-context-pi) · [acp-kernel](https://github.com/ranxianglei/acp-kernel) · [opencode-acp](https://github.com/ranxianglei/opencode-acp) · [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) diff --git a/docs/presets-design.md b/docs/presets-design.md index aff0405..94b6b0c 100644 --- a/docs/presets-design.md +++ b/docs/presets-design.md @@ -22,7 +22,7 @@ ## 2. 关键依赖事实(已验证) -- **#75 Phase 1 尚未合入 main。** main = `bb9f2f6`(release v0.2.21),无 `src/settings.ts`;分支 `feat/runtime-settings-75` 有该文件但未合并,且基于 v0.2.20 之前。PR 合并仅人工,无法拉进一个以 main 为基的 PR。 +- **#75 Phase 1 已合入 main(随 v0.2.22 发布)。** 本段记录的是合入前的状态:当时 main = `bb9f2f6`(release v0.2.21),无 `src/settings.ts`;分支 `feat/runtime-settings-75` 有该文件但未合并,且基于 v0.2.20 之前。PR 合并仅人工,无法拉进一个以 main 为基的 PR。 - **因此预设先落在组合配置层**:引擎构造时读 `config.preset`,随 bundle 安装或 `cordis.patch.yml` 的 `config:` 生效,今天就能用。等 #75 把六个标量键接进 settings 命名空间后,再把 `preset` 别名暴露到同一通道是个小跟进(不与 #75 冲突——#75 加的是六个标量键,不是预设别名,两者正交)。 - **拼错 preset 会让 profile 起不来**:bundle 行本身刻意不带 `config`(AGENTS.md 硬性规则 8),所以 `preset` 只能来自用户自己写的同 id `compaction-acp` 行;该行构造抛错即挂载失败,profile 会在配置修好前一直无法启动。这是 fail-fast 的既定行为(与自定义提示词模板同一类),值得在 README 里说明,避免用户把它当成崩溃。 diff --git a/package-lock.json b/package-lock.json index 73c488e..9e1c718 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "billion-context-dsh", - "version": "0.2.21", + "version": "0.2.22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "billion-context-dsh", - "version": "0.2.21", + "version": "0.2.22", "license": "MIT", "devDependencies": { "@deepseek-ai/cordis": "4.0.2", diff --git a/package.json b/package.json index 8942149..ea1d559 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "billion-context-dsh", - "version": "0.2.21", + "version": "0.2.22", "description": "Active Context Pruning (ACP) for the DeepSeek Harness — model-driven context management as a CompactionEngine backend.", "keywords": [ "deepseek",