billion-context-dsh 0.2.11 → 0.2.13

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.en.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [English](./README.en.md) | [中文](./README.md)
4
4
 
5
5
  > **⚠️ Beta notice — not for production use**
6
- > This project (**v0.2.11**) 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.
6
+ > This project (**v0.2.13**) 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.
7
7
 
8
8
  <p align="center">
9
9
  <strong>Built with gratitude on top of these projects</strong> — please give them a ⭐:
@@ -53,25 +53,53 @@ This is the DeepSeek Harness port of [billion-context-pi](https://github.com/ran
53
53
 
54
54
  > 💡 **Want DeepSeek Harness to install it for you?** This repo itself runs on DSH: hand [docs/INSTALL.md](docs/INSTALL.md) to an agent in a session and it will read the guide, inspect your profile, wire the composition, and verify the mount. Two preconditions: ① the config lives under `~/.dsh`, so you approve one file-permission prompt; ② afterwards ask it to call `acp_status` as proof.
55
55
 
56
+ **Path A (recommended): one-command install via the DSH store / `dsh plugin` (bundle) — globally active right after install, zero configuration.**
57
+
58
+ Click install in DSH's plugin store, or run:
59
+
56
60
  ```bash
57
- npm install billion-context-dsh
61
+ dsh plugin --profile web add billion-context-dsh
58
62
  ```
59
63
 
60
- > 💡 **One-command install via `dsh plugin` (bundle, v0.2.0+)**. The package declares a `dsh.bundle`
61
- > manifest, so DSH's plugin command installs it into the profile and applies the patch
62
- > automatically (equivalent to the composition row below):
64
+ The command installs the package and automatically layers this package's bundle patch ([cordis.patch.yml](cordis.patch.yml)) into the profile's composition. The patch does two things:
65
+
66
+ - **Disables the host `compaction-basic`** — so two backends do not both register `ctx.compaction` in the same realm (modern DSH web bundles already ship this disable; the row is an idempotent safety net that holds on every supported DSH);
67
+ - **Mounts the ACP engine at the HOST plane** — the four model tools (`compress` / `decompress` / `search_context` / `acp_status`), the `/acp` command, the advisory nudge, and the ACP guidance section reach **EVERY mode** of the profile (standard / code / minimal / cordis / custom presets). Window auto-detection and the tools/command/nudge defaults are all on — **no manual configuration needed**.
68
+
69
+ Restart `dsh` afterwards (bundle layers are composed at startup), open a new session, and verify: ask the model to call `acp_status`, or run `/acp status`. Shipped presets (standard / code / cordis) keep their realm-local `compaction-basic` fallback (automatic pressure compression still runs there; the ACP tools and nudge coexist); minimal and presets without a compaction realm use this engine directly.
70
+
71
+ > **DSH version compatibility.** The package declares the peer range
72
+ > `^0.1.0-rc.6 || ^0.1.1-rc.1` for `@deepseek-ai/dsh-compaction`, covering both the
73
+ > `0.1.0-rc.x` and `0.1.1-rc.x` release lines (including the current DSH release;
74
+ > the seam's `src/` is unchanged from `0.1.0-rc.6` to `0.1.1-rc.2`, so the public
75
+ > API is identical). The range is two `||` clauses **on purpose**: npm
76
+ > (node-semver) only lets a prerelease version satisfy a range that carries a
77
+ > comparator on the SAME `[major, minor, patch]` tuple as the candidate, so a lone
78
+ > `^0.1.0-rc.6` can never match `0.1.1-rc.x` (issue #68) — older releases fail to
79
+ > install on DSH 0.1.1-rc.x; upgrade to a release containing this fix.
80
+
81
+ **Path B: plain `npm install` (package only — a composition row is required).**
63
82
 
64
83
  ```bash
65
- dsh plugin --profile web add billion-context-dsh
84
+ npm install billion-context-dsh
66
85
  ```
67
86
 
68
- Restart `dsh` afterwards (bundle layers are composed at startup). For custom `config`
69
- (such as `modelContextLimit` / `prompts`), keep the hand-written composition row — the
70
- bundle patch ([cordis.patch.yml](cordis.patch.yml)) only inserts the default row without `config`.
87
+ This only installs the package into your project/global store; it does **not** touch any profile — add a composition row as shown below or the engine never mounts.
71
88
 
72
- That's it. Then add a composition row where a compaction backend is expected — two scopes, pick by how wide you want it:
89
+ ## Scope & customization
90
+
91
+ Two audiences: ① Path B (plain npm install) users, who must write a composition row; ② Path A users who want custom `config` (the bundle already ships sane defaults — override them with a SAME-ID row).
92
+
93
+ **Custom `config` (Path A bundle users).** Append a `compaction-acp` row with `config:` to your profile patch (e.g. `~/.dsh/profiles/web/cordis.patch.yml`) — the same-id row overrides the bundle's default row:
94
+
95
+ ```yaml
96
+ - id: compaction-acp
97
+ name: 'billion-context-dsh'
98
+ config:
99
+ modelContextLimit: 128000 # optional; omit to auto-detect the model's real window (fallback 128000)
100
+ ```
73
101
 
74
- **Global — host plane, every mode** (recommended). In your profile patch (e.g. `~/.dsh/profiles/web/cordis.patch.yml`), add:
102
+ **Global — host plane, every mode** (recommended). This is what Path A's bundle already does; plain-npm users add all of the following (bundle users skip the first two rows):
75
103
 
76
104
  ```yaml
77
105
  # ACP as the global compaction backend: four model tools + `/acp` command +
@@ -79,6 +107,7 @@ That's it. Then add a composition row where a compaction backend is expected —
79
107
  # (standard / code / minimal / cordis / custom presets).
80
108
  # Must also disable the host compaction-basic: two backends providing
81
109
  # `ctx.compaction` in the same realm collide.
110
+ # (The bundle install already ships these two rows.)
82
111
  - id: compaction-basic
83
112
  disabled: true
84
113
 
@@ -173,9 +202,9 @@ This project reuses `acp-kernel`'s compression core and `billion-context-pi`'s d
173
202
  | `modelContextLimit` | auto-detected (fallback `128000`) | Context window used for the kernel's pressure decisions; an explicit value wins and skips the probe |
174
203
  | `autoModelContextLimit` | `true` | Probe the model's real window from the model API (`agent.ctx.llm.resolveModelInfo`); fall back to the default on failure, the `/acp` command shows the window source (the `acp_status` model tool carries no window info). A failed probe is surfaced in the host log and the `/acp` panel (`restart to re-probe`) — the failure is cached like a success, so fixing the gateway requires a restart or an explicit `modelContextLimit` before the probe retries |
175
204
  | `nudgeMinContextLimitPct` | kernel default `0.45` | Nudge window lower bound (usage fraction) — validation only; the growth-driven trigger has no percentage floor — same default as billion-context-pi |
176
- | `nudgeMaxContextLimitPct` | engine default `0.70` (kernel/pi default `0.75`) | Over-limit line: above this the nudge fires regardless of growth — deliberately below the host compaction-basic 80% auto-compaction line so the forced nudge fires first; an explicit value wins |
177
- | `nudgeEmergencyThresholdPct` | engine default `0.85` (kernel/pi default `0.95`) | Emergency nudge (bypasses the per-turn dedup) — lowered from `0.95`: at 95% the model has no room to act and the 80% auto-compaction line shadows it; an explicit value wins |
178
- | `coreOverrides` | — | Any other acp-kernel `Config` override (billion-context-pi's `coreOverrides` escape hatch) |
205
+ | `nudgeMaxContextLimitPct` | engine default `0.70` (kernel/pi default `0.75`) | Over-limit line: above this the nudge fires regardless of growth — deliberately below the host compaction-basic 80% auto-compaction line so the forced nudge fires first; an explicit value wins (a same-name key in `coreOverrides.nudge` outranks it — see below) |
206
+ | `nudgeEmergencyThresholdPct` | engine default `0.85` (kernel/pi default `0.95`) | Emergency nudge (bypasses the per-turn dedup) — lowered from `0.95`: at 95% the model has no room to act and the 80% auto-compaction line shadows it; an explicit value wins (a same-name key in `coreOverrides.nudge` outranks it — see below) |
207
+ | `coreOverrides` | — | Any other acp-kernel `Config` override (billion-context-pi's `coreOverrides` escape hatch). Merge order: kernel defaults → top-level pct knobs → `coreOverrides.nudge` lands last — same-name keys take its value |
179
208
  | `autoTools` | `true` | Register the four model tools on `ctx.tools` |
180
209
  | `autoCommand` | `true` | Register the `/acp` command on `ctx.commands` |
181
210
  | `autoNudge` | `true` | Inject the nudge into `agent/pre-step` |
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [中文](./README.md) | [English](./README.en.md)
4
4
 
5
5
  > **⚠️ 测试版声明——请勿用于生产环境**
6
- > 本项目(**v0.2.11**)仍处于开发中的测试版。[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 本身也处于**公开测试版**阶段。**请勿将两者用于工程化 / 生产环境**——预期会有破坏性变更与粗糙之处。
6
+ > 本项目(**v0.2.13**)仍处于开发中的测试版。[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 本身也处于**公开测试版**阶段。**请勿将两者用于工程化 / 生产环境**——预期会有破坏性变更与粗糙之处。
7
7
 
8
8
  <p align="center">
9
9
  <strong>衷心感谢以下项目——请给它们一个 ⭐:</strong>
@@ -56,30 +56,58 @@
56
56
  > 你的 profile、编辑组合配置并验证挂载。前提:① 配置写在 `~/.dsh` 下,需要
57
57
  > 你批准一次文件权限;② 装完让它调用 `acp_status` 自证。
58
58
 
59
+ **方式一(推荐):DSH 商店 / `dsh plugin` 一键装(bundle)——装完即全局生效,零配置。**
60
+
61
+ 在 DSH 的插件商店里点安装,或命令行执行:
62
+
59
63
  ```bash
60
- npm install billion-context-dsh
64
+ dsh plugin --profile web add billion-context-dsh
61
65
  ```
62
66
 
63
- > 💡 **v0.2.0 起支持 `dsh plugin` 一键安装(bundle)**。包已声明 `dsh.bundle`
64
- > manifest,DSH 的插件命令会把它装进 profile 并自动应用补丁(等价于下面的组合行):
67
+ 命令内部会装包并把本包的 bundle 补丁([cordis.patch.yml](cordis.patch.yml))自动挂进该 profile 的层栈。补丁做了两件事:
68
+
69
+ - **禁用 host 的 `compaction-basic`**——避免同一 realm 内两个后端同时注册 `ctx.compaction` 冲突(现代 DSH 的 web bundle 已自带该禁用,此行为幂等兜底,任何受支持版本下都成立);
70
+ - **把 ACP 引擎挂到 host 平面**——四种模型工具(`compress` / `decompress` / `search_context` / `acp_status`)、`/acp` 命令、nudge、ACP 提示词段对该 profile 的**所有模式**(standard / code / minimal / cordis / 自定义预设)生效。窗口自动探测、工具/命令/nudge 默认全开,**无需任何手工配置**。
71
+
72
+ 装完**重启 `dsh`**(bundle 层在启动时组合),新开会话即可用——让模型调用 `acp_status` 或执行 `/acp status` 自证。shipped 预设(standard / code / cordis)内部的 realm 级 `compaction-basic` 自动压缩兜底仍然保留(这些模式里"自动摘要"照旧,ACP 工具与 nudge 并存);minimal 等不带 compaction realm 的预设直接使用本引擎。
73
+
74
+ > **与 DSH 版本的兼容性。** 包声明 peer 依赖 `@deepseek-ai/dsh-compaction` 为
75
+ > `^0.1.0-rc.6 || ^0.1.1-rc.1`,同时覆盖 `0.1.0-rc.x` 与 `0.1.1-rc.x` 两条 rc 线
76
+ > (含当前最新 DSH release;从 `0.1.0-rc.6` 到 `0.1.1-rc.2`,seam 的 `src/` 源码
77
+ > 零改动,公开 API 完全一致)。范围写成两个并集子句是**有意为之**:npm
78
+ > (node-semver)的预发布匹配规则要求 range 里存在与候选版本**相同
79
+ > `[major, minor, patch]` 元组**的比较器,单一 `^0.1.0-rc.6` 永远匹配不了
80
+ > `0.1.1-rc.x`(issue #68)——因此旧发布的包在 DSH 0.1.1-rc.x 上装不上,
81
+ > 升级到含本次修复的新版本即可。
82
+
83
+ **方式二:纯 `npm install`(只装包,需要手写组合行)。**
65
84
 
66
85
  ```bash
67
- dsh plugin --profile web add billion-context-dsh
86
+ npm install billion-context-dsh
68
87
  ```
69
88
 
70
- 装完重启 `dsh`(bundle 层在启动时组合)。需要自定义 `config`(如
71
- `modelContextLimit` / `prompts`)时仍建议手写组合行——bundle 补丁
72
- ([cordis.patch.yml](cordis.patch.yml))只插入无 `config` 的默认行。
89
+ 这只把包装进你的项目/全局,**不会**触碰任何 profile——请按下方「两种生效范围与自定义」手写组合行,引擎才会挂载。
73
90
 
74
- 就这样。然后在需要压缩后端的位置加组合配置——两种范围,按需选择:
91
+ ## 两种生效范围与自定义
92
+
93
+ 本节服务于两类人:① 方式二(纯 npm 安装,必须手写组合行);② 方式一用户想自定义 `config`(bundle 已有默认行为,只需用**同 id** 行覆盖)。
94
+
95
+ **自定义 config(方式一 bundle 用户)。** 在你的 profile 补丁(如 `~/.dsh/profiles/web/cordis.patch.yml`)里追加一个 `compaction-acp` 行并附 `config:`——同 id 行覆盖 bundle 的默认行:
96
+
97
+ ```yaml
98
+ - id: compaction-acp
99
+ name: 'billion-context-dsh'
100
+ config:
101
+ modelContextLimit: 128000 # 可选;省略时自动探测模型真实窗口(回退 128000)
102
+ ```
75
103
 
76
- **全局生效(host 平面,所有模式)——推荐**。在你的 profile 补丁(如 `~/.dsh/profiles/web/cordis.patch.yml`)中追加:
104
+ **全局生效(host 平面,所有模式)——推荐**。这是方式一 bundle 的默认行为;纯 npm 安装的用户在 profile 补丁中追加以下全部内容(bundle 用户跳过前两行):
77
105
 
78
106
  ```yaml
79
107
  # ACP 作为全局压缩后端:四个模型工具 + `/acp` 命令 + nudge + ACP 提示词段,
80
108
  # 对所有模式(standard / code / minimal / cordis / 自定义预设)生效。
81
109
  # 必须同时禁用 host 的 compaction-basic:同一 realm 内两个后端同时
82
- # provide `ctx.compaction` 会冲突。
110
+ # provide `ctx.compaction` 会冲突。(bundle 安装已自动带上这两行。)
83
111
  - id: compaction-basic
84
112
  disabled: true
85
113
 
@@ -174,9 +202,9 @@ DSH 的每个模型请求都派生自其 append-only 会话日志(*surface*)
174
202
  | `modelContextLimit` | 自动探测(回退 `128000`) | 用于内核压力决策的上下文窗口;显式配置时优先且跳过探测 |
175
203
  | `autoModelContextLimit` | `true` | 从模型 API 自动探测真实窗口(`agent.ctx.llm.resolveModelInfo`);探测失败回退默认值,`/acp` 命令展示窗口来源(模型工具 `acp_status` 不含窗口信息)。探测失败会在宿主日志与 `/acp` 面板提示(`restart to re-probe`)——失败结果同样被缓存,修复网关后需重启或显式设置 `modelContextLimit` 才会重新探测 |
176
204
  | `nudgeMinContextLimitPct` | 内核默认 `0.45` | Nudge 窗口下界(用量占比)——仅作配置校验,增长路径的触发没有百分比下限——与 billion-context-pi 相同的默认值 |
177
- | `nudgeMaxContextLimitPct` | engine 默认 `0.70`(内核/pi 默认 `0.75`) | 过限线:超过此值则无论增长与否都触发 nudge——刻意低于宿主 compaction-basic 的 80% 自动压缩线,保证强制 nudge 先触发;显式配置优先 |
178
- | `nudgeEmergencyThresholdPct` | engine 默认 `0.85`(内核/pi 默认 `0.95`) | 紧急 nudge(绕过每轮去重)——从 `0.95` 下调:95% 时模型已无操作空间且会被 80% 自动压缩线遮蔽;显式配置优先 |
179
- | `coreOverrides` | — | 任何其他 acp-kernel `Config` 覆盖(billion-context-pi 的 `coreOverrides` 逃生口) |
205
+ | `nudgeMaxContextLimitPct` | engine 默认 `0.70`(内核/pi 默认 `0.75`) | 过限线:超过此值则无论增长与否都触发 nudge——刻意低于宿主 compaction-basic 的 80% 自动压缩线,保证强制 nudge 先触发;显式配置优先(`coreOverrides.nudge` 同名键优先级更高,见下) |
206
+ | `nudgeEmergencyThresholdPct` | engine 默认 `0.85`(内核/pi 默认 `0.95`) | 紧急 nudge(绕过每轮去重)——从 `0.95` 下调:95% 时模型已无操作空间且会被 80% 自动压缩线遮蔽;显式配置优先(`coreOverrides.nudge` 同名键优先级更高,见下) |
207
+ | `coreOverrides` | — | 任何其他 acp-kernel `Config` 覆盖(billion-context-pi 的 `coreOverrides` 逃生口)。合并顺序:内核默认 → 顶层 pct 配置 → `coreOverrides.nudge` 最后落地——同名键以它为准 |
180
208
  | `autoTools` | `true` | 在 `ctx.tools` 注册四个模型工具 |
181
209
  | `autoCommand` | `true` | 在 `ctx.commands` 注册 `/acp` 命令 |
182
210
  | `autoNudge` | `true` | 当内核建议时向 `agent/pre-step` 注入 nudge |
package/cordis.patch.yml CHANGED
@@ -1,11 +1,32 @@
1
- # dsh bundle patch: inserts the ACP compaction backend into a profile's layer stack.
1
+ # dsh bundle patch: makes billion-context-dsh ACTIVE right after a one-command
2
+ # install — the plugin store and `dsh plugin --profile web add
3
+ # billion-context-dsh` both run the same command, and this file (declared in
4
+ # package.json as `dsh.bundle.patch`) becomes a layer of the profile's
5
+ # composition automatically. No manual configuration is needed.
2
6
  #
3
- # This is what makes the package installable via `dsh plugin --profile web add
4
- # billion-context-dsh` (declared in package.json as `dsh.bundle.patch`). The row
5
- # below is exactly the manual composition row documented in docs/INSTALL.md (§2a),
6
- # minus config: omitting `modelContextLimit` means auto-detection (fallback 128000),
7
- # and the built-in prompt copy (config.prompts) is used. Users who want custom
8
- # config can still write the row by hand in their profile patch.
7
+ # Two rows land in the profile's composition root:
8
+ # 1. `compaction-basic` disabled the host's own auto-compaction backend
9
+ # would otherwise register `ctx.compaction` at the root realm too, and
10
+ # only one provider per realm may own that service name. (On dsh
11
+ # 0.1.0-rc.6+ the web-app bundle already ships this disable; the row is
12
+ # idempotent and keeps the plugin self-sufficient on every supported DSH.)
13
+ # 2. `compaction-acp` — the ACP engine, mounted at the HOST plane, so its
14
+ # model tools (`compress`, `decompress`, `search_context`, `acp_status`),
15
+ # the `/acp` command, the advisory nudge, and the guidance section reach
16
+ # EVERY mode (standard / code / minimal / cordis / custom presets) of the
17
+ # profile the plugin was installed into.
18
+ #
19
+ # No `config` is set on purpose: the context window is auto-detected from the
20
+ # model API (fallback 128000) and the built-in prompt copy is used. Users who
21
+ # want custom config write a SAME-ID `compaction-acp` row in their profile's
22
+ # own `cordis.patch.yml` — it overrides this row (see README).
23
+ #
24
+ # Shipped presets (standard / code / cordis) keep their realm-local
25
+ # compaction-basic fallback (automatic pressure compression); minimal and
26
+ # presets without a compaction realm use the host ACP engine directly.
27
+ - id: compaction-basic
28
+ disabled: true
29
+
9
30
  - insert:
10
31
  - id: compaction-acp
11
- name: 'billion-context-dsh'
32
+ name: 'billion-context-dsh'
package/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ import { CompactionEngine, type CompactionAgentContext, type CompactionResult, t
30
30
  import { type CompressionCore } from 'acp-kernel';
31
31
  import type { Agent } from '@deepseek-ai/dsh-agent';
32
32
  import { AcpStateStore } from './state.ts';
33
+ import { type ToolEnvironment } from './tools.ts';
33
34
  import { type AcpPrompts, type ResolvedPrompts } from './prompts.ts';
34
35
  import { type AcpWindow } from './window.ts';
35
36
  export { AcpStateStore } from './state.ts';
@@ -59,7 +60,8 @@ export interface AcpConfig {
59
60
  * kernel injects a nudge regardless of growth or cadence. Engine default
60
61
  * 0.70 (deliberately BELOW the kernel/billion-context-pi default 0.75 and
61
62
  * the host compaction-basic auto-compaction line 0.80, so the forced nudge
62
- * always fires first); an explicit value wins.
63
+ * always fires first); an explicit value wins over this default — a
64
+ * same-name key in `coreOverrides.nudge` wins over both (it merges last).
63
65
  */
64
66
  readonly nudgeMaxContextLimitPct?: number;
65
67
  /**
@@ -69,7 +71,11 @@ export interface AcpConfig {
69
71
  * compaction-basic line shadows it in standard/code/cordis modes).
70
72
  */
71
73
  readonly nudgeEmergencyThresholdPct?: number;
72
- /** Any other acp-kernel Config override (billion-context-pi's `coreOverrides` escape hatch). */
74
+ /**
75
+ * Any other acp-kernel Config override (billion-context-pi's `coreOverrides`
76
+ * escape hatch). Merge order per section: kernel defaults → the engine pct
77
+ * knobs above → these keys land LAST, so a same-name key here wins.
78
+ */
73
79
  readonly coreOverrides?: Partial<import('acp-kernel').Config>;
74
80
  /**
75
81
  * Custom token-count function for the kernel's internal estimation.
@@ -107,6 +113,14 @@ export declare class AcpCompactionEngine extends CompactionEngine {
107
113
  readonly config: AcpConfig;
108
114
  /** Resolved prompt templates (validated at construction — fail-fast on template typos). */
109
115
  readonly prompts: ResolvedPrompts;
116
+ /**
117
+ * The environment wired into tools / command / nudge. Exposed so tests (and
118
+ * introspection) can assert the forwarding actually happened: the config
119
+ * chain user config → this.config → env → kernelConfigFor is all OPTIONAL
120
+ * fields, so a dropped forwarding line fails typecheck silently and would
121
+ * revive lost-config bugs with every unit test green.
122
+ */
123
+ readonly env: ToolEnvironment;
110
124
  private readonly lastNudgeTurn;
111
125
  /** Successful compress call ids awaiting their tool/result so the pair can be hidden. */
112
126
  private readonly compressCallIdsToHide;
package/dist/index.js CHANGED
@@ -3511,8 +3511,12 @@ function kernelConfigFor(input) {
3511
3511
  if (input.nudgeMaxContextLimitPct !== void 0) nudgePatch.maxContextLimitPct = input.nudgeMaxContextLimitPct;
3512
3512
  if (input.nudgeEmergencyThresholdPct !== void 0) nudgePatch.emergencyThresholdPct = input.nudgeEmergencyThresholdPct;
3513
3513
  const overrides = { ...input.coreOverrides };
3514
- if (Object.keys(nudgePatch).length > 0) {
3515
- overrides.nudge = { ...defaultConfig(input.modelContextLimit).nudge, ...nudgePatch };
3514
+ if (Object.keys(nudgePatch).length > 0 || input.coreOverrides?.nudge) {
3515
+ overrides.nudge = {
3516
+ ...defaultConfig(input.modelContextLimit).nudge,
3517
+ ...nudgePatch,
3518
+ ...input.coreOverrides?.nudge
3519
+ };
3516
3520
  }
3517
3521
  return defaultConfig(input.modelContextLimit, overrides);
3518
3522
  }
@@ -4438,7 +4442,9 @@ var DEFAULT_CONFIG = {
4438
4442
  // kernel/billion-context-pi 0.75/0.95. 0.95 leaves no room to act before
4439
4443
  // the API rejects, and the host's compaction-basic line (thresholdRatio
4440
4444
  // 0.80) shadows it in standard/code/cordis modes; 0.70 keeps the forced
4441
- // over-limit nudge ahead of that 80% line. Explicit values always win.
4445
+ // over-limit nudge ahead of that 80% line. Explicit values always win
4446
+ // against these defaults — `coreOverrides` merges last and beats them on
4447
+ // same-name keys.
4442
4448
  nudgeMaxContextLimitPct: 0.7,
4443
4449
  nudgeEmergencyThresholdPct: 0.85
4444
4450
  };
@@ -4454,6 +4460,14 @@ var AcpCompactionEngine = class extends CompactionEngine {
4454
4460
  config;
4455
4461
  /** Resolved prompt templates (validated at construction — fail-fast on template typos). */
4456
4462
  prompts;
4463
+ /**
4464
+ * The environment wired into tools / command / nudge. Exposed so tests (and
4465
+ * introspection) can assert the forwarding actually happened: the config
4466
+ * chain user config → this.config → env → kernelConfigFor is all OPTIONAL
4467
+ * fields, so a dropped forwarding line fails typecheck silently and would
4468
+ * revive lost-config bugs with every unit test green.
4469
+ */
4470
+ env;
4457
4471
  lastNudgeTurn = /* @__PURE__ */ new Map();
4458
4472
  /** Successful compress call ids awaiting their tool/result so the pair can be hidden. */
4459
4473
  compressCallIdsToHide = /* @__PURE__ */ new Set();
@@ -4479,6 +4493,7 @@ var AcpCompactionEngine = class extends CompactionEngine {
4479
4493
  prompts: this.prompts,
4480
4494
  compressCallIdsToHide: this.compressCallIdsToHide
4481
4495
  };
4496
+ this.env = env;
4482
4497
  const tools = ctx.get("tools");
4483
4498
  if (tools !== void 0) {
4484
4499
  for (const tool of makeTools(env)) tools.register(tool);