Skip to content

(feat) runtime settings — six scalar knobs hot-editable via settings.yaml / /acp config - #76

Open
Tyan66666 wants to merge 5 commits into
mainfrom
feat/runtime-settings-75
Open

(feat) runtime settings — six scalar knobs hot-editable via settings.yaml / /acp config#76
Tyan66666 wants to merge 5 commits into
mainfrom
feat/runtime-settings-75

Conversation

@Tyan66666

Copy link
Copy Markdown
Owner

Problem

The plugin's configuration lived only in the composition row (cordis.patch.yml): changing a knob like nudgeMaxContextLimitPct meant editing YAML and restarting the process. There was no way to adjust the config-file-configurable settings at runtime.

Cause

The engine read its six scalar knobs once at construction from the resolved config; with no runtime settings layer, a file edit could not reach a running session.

Fix (phase 1 of #75)

Wire the six scalar knobs (modelContextLimit, autoModelContextLimit, nudgeMinContextLimitPct, nudgeMaxContextLimitPct, nudgeEmergencyThresholdPct, autoNudge) through the host settings layer via the official installSettingsSection seam (@deepseek-ai/dsh-settings, namespace compaction-acp):

  • editing ~/.dsh/settings.yaml — or the new /acp config subcommand — hot-applies to running sessions, no restart;
  • layering per key: schema default → composition row (config:) → user settings section; /acp config reset returns a key to the composition row / engine default;
  • changing a window key clears the window-probe cache, so a fixed gateway is re-probed on the next step;
  • settingsEnabled: false is a composition-only kill switch (deliberately not exposed through settings itself — a switch cannot turn off its own plumbing);
  • the composition base handed to the settings layer is filtered to schema-known keys — raw rows carry prompts/coreOverrides/countTokens (object/function values) that must never enter the settings layer;
  • probe-failure copy now points at /acp config instead of "restart only".

Design: docs/settings-integration-design.md (reviewed by three agent review teams before implementation).

Verification

  • 188/188 tests pass (12 new: pure units incl. the false-value parse regression, E2E with a real engine + in-memory settings provider, kill switch, HMR-style remount gate; the peer-range test now also guards the dsh-settings dual-tuple range);
  • npm run typecheck and npm run build green;
  • deps: new peer @deepseek-ai/dsh-settings (^0.1.0-rc.6 || ^0.1.1-rc.1, per issue peerDependencies "dsh-compaction@^0.1.0-rc.6" 永远匹配不了 0.1.1-rc.2(semver 预发布元组规则)— 最新 DSH 上装不上 #68) + @deepseek-ai/schemastery (^3.18.1); dev deps pinned exact (legacy dsh-token-meter caret fixed);
  • docs in the same PR: README (zh/en) runtime-settings section + config-table markers, INSTALL note, AGENTS.md module map, docs index.

Part of #75 — the browser settings card (phase 3) remains blocked upstream (WEB_SETTINGS_NAMESPACES allowlist in dsh-host-apiproxy).

…yaml / /acp config

Phase 1 of issue #75: the six scalar knobs (modelContextLimit,
autoModelContextLimit, nudgeMin/Max/EmergencyPct, autoNudge) now resolve
through the host settings layer (installSettingsSection seam) — editing
~/.dsh/settings.yaml or the new /acp config subcommand applies to running
sessions without a restart. Window-key changes clear the probe cache so a
fixed gateway re-probes; settingsEnabled:false is a composition-only kill
switch. New deps: peer @deepseek-ai/dsh-settings (dual-tuple range) +
schemastery peer; dev deps pinned exact (token-meter caret fixed). 188 tests
pass incl. E2E via an in-memory provider + the HMR remount gate.
…TS.md module map + design doc

Config table rows carry runtime-adjustable markers, a new README section
covers settings.yaml / /acp config usage and the kill switch, the window
probe-failure copy now points at /acp config, and the docs index lists the
new design doc.
@Tyan66666
Tyan66666 force-pushed the feat/runtime-settings-75 branch from a1f9bd1 to ec4cd15 Compare September 6, 2026 11:01
@Tyan66666

Copy link
Copy Markdown
Owner Author

更新说明(rebase 到最新 main + 勘探结论 + dist 重建)

本 PR 原基于 v0.2.13(7dad118),已 rebase 到当前 main(08c68d5,含 #96 / #101 / #102),解决了全部冲突并重新验证。

冲突解决(union 原则:main 新行为 + 本 PR 新增)

  • package.json:保留 main 的四个 seam 三 clause peer(^0.1.0-rc.6 || ^0.1.1-rc.1 || ^0.1.2-alpha.4)+ 本 PR 新增的 "@deepseek-ai/dsh-settings": "^0.1.0-rc.6 || ^0.1.1-rc.1""@deepseek-ai/schemastery": "^3.18.1"决定不加 0.1.2 clause:实机 web profile 的 dsh-settings 实际版本是 0.1.0-rc.8,已被现有双 clause 覆盖;dsh-settings 尚无 0.1.x 正式线,随宿主盲升反而破坏「稳定测试基线」规则。
  • package-lock.json:按合并后的 package.json 重新生成(npm install --package-lock-only)。
  • tests/peer-range.test.ts:保留 main 的 seamPeers 循环版,追加本 PR 的 settings 双 clause 断言;丢弃引用已不存在变量的旧版四 seam 测试。
  • AGENTS.md / README(zh/en):保留 main 的 (fix) 窗口探测优先读宿主投影——会话中途切模型后不再误报 300% 假紧急 nudge #89 窗口探测新文案(投影优先),叠加本 PR 的热调注解——/acp configmodelContextLimit/autoModelContextLimit 会清空窗口缓存、改完即重探;coreOverrides 标注「只读:组合行专用,不经 settings 层」。

新增提交

  • bcce217 docs: 设计文档补「浏览器设置卡片·勘探更新(2026-09-06)」:DSH 0.1.2 线上 WEB_SETTINGS_NAMESPACES 白名单已不存在,替代机制为 SettingsController.describe() 动态描述全部注册 namespace + 客户端槽位 settings.section / settings.plugins.tab / settings.plugin.item;第三方插件 UI 官方路径 = dsh.client 清单 + ./client 导出(cordis-client-runner 浏览器加载)。阶段三(UI 卡片)的门禁已解除,剩余工作已列入 §5(自建 client 卡片、tsup client 入口、对旧宿主降级);rc.6 时代记录保留为历史。

dist 重建

验证

  • npm run typecheck
  • npm test215/215 通过(main 基线 + 本 PR 新增 settings/peer-range 用例)
  • npm run build
  • devDeps 全部钉在 0.1.0-rc.6 线;acp-kernel 精确 pin 不变

@Tyan66666

Copy link
Copy Markdown
Owner Author

CI 修复:package-lock.json 丢了跨平台 optional 依赖(fcef379)

现象:首次推送后 CI 在 Typecheck 步骤失败(12 秒),报 Unable to resolve @typescript/typescript-linux-x64——linux 跑步机上装不出 TypeScript 7 的原生二进制。

原因:rebase 解冲突时我用 npm install --package-lock-only 重新生成了 package-lock.json。npm 10.9.8 的这个模式(以及带现存 lock 的普通 install)会按当前平台剪掉 optional 依赖:lock 从 174 个包缩到 81 个,@typescript/typescript-*@esbuild/*@rollup/* 等全部非 darwin 平台二进制条目丢失,linux 上的 npm ci 自然装不出来(本机 macOS 全绿,CI 一跑就暴露)。

修复:以 main 的 package-lock.json 为基底,只注入本 PR 的真实增量(根条目:dsh-settings devDep 钉版、dsh-token-meter 精确钉版、peer 新增 dsh-settings/schemastery 两行;新增 node_modules/@deepseek-ai/dsh-settings 条目),其余 174 个条目与 main 逐字节一致。本地 npm ci(对 lock↔package.json 一致性是硬校验)通过,typecheck / 215 tests / build 复验通过。

结论:CI 已转绿(ci ✅ / pr-title ✅,mergeable CLEAN)。后续在本仓库重新生成 lock 时应避免 --package-lock-only,改用全量 npm install 并核对平台二进制条目数。

@ranxianglei

Copy link
Copy Markdown
Contributor

我来协助看一下这个问题,请分析并回复处理结果。

@ranxianglei

ranxianglei commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

🤖 ework agent · qwen3.8-27b

已按你的要求完整分析并本地验证完毕。结论先行:代码审查通过、功能实现质量高,可以合入;当前唯一的阻塞项是 main 在 PR 打开期间前进了 7 个提交(到 v0.2.21),分支需要 rebase。我用一次试验性合并证明了所有冲突都可干净解决,合并后全套 228/228 测试通过。细节如下。

一、PR head(fcef379)独立验证 —— 全绿

在干净的临时目录里 git archive 取出 PR 头提交,按 CI 同款流程跑:

步骤 结果
npm ci ✅ 81 packages(linux-x64,tsc 原生二进制正常解析——顺带实证了 floor 2 的 lockfile 修复在 Linux 上有效)
npm run typecheck ✅ 严格 TS 零错误
npm test 215/215 通过
npm run build ✅ tsup 打包成功(dist/index.js 201.39 KB)

PR 描述里声称的验证数据属实。

二、代码审查意见

整体评价:设计克制、边界清晰,符合本仓库的既有规范(kernel owns / engine wires、docs-self-documenting、peer range 的 semver 元组规则都有守)。src/settings.ts(249 行新模块)、src/index.ts 接线、src/commands.ts/acp configtests/settings.test.ts(12 个 M6 测试含 E2E 与 kill switch)都逐行看过,没有问题。几个值得写进记录的点:

  1. schemastery 作为 external peer 是安全的——我查了 @deepseek-ai/dsh-settings@0.1.0-rc.6 的 package.json:它自己就把 @deepseek-ai/schemastery: ^3.18.1 声明为 peerDependency。任何能提供 dsh-settings 的宿主必然同时提供 schemastery,所以 tsup 保持两者 external(external: [/^@deepseek-ai\//])是正确的宿主接缝模式,不需要像 acp-kernel 那样内联。
  2. minor:configResetText 缺冲突兜底(src/commands.ts)——set 路径对 SettingsConflictError 有 try/catch 并返回友好重试文案,但 reset 路径直接调 surface.replaceSection(...) 没有捕获,并发冲突时会以裸 rejection 冒泡而不是友好提示。建议 rebase 时顺手补上(一行 try/catch)。
  3. minor:注释与行为不符(src/index.ts applySettings)——注释说 "keep the last good",但 current = next 在 try 之前已经交换;实际无害(handler 只清缓存/打日志),建议把注释改准。
  4. semantic(审查中发现,rebase 时必须处理):windowFor 里探测路径的门控改成了 live 读(!live.autoModelContextLimit),但投影路径的门控仍留在 this.config.autoModelContextLimit——而 README 明确承诺"投影与探测在 autoModelContextLimit: false 时均跳过"。后果:运行时把该键从 true 热改成 false 后,投影路径仍在生效,热改只生效了一半。修复就是把投影门控也换成 live.(一个词)。我在下面的试验合并里已经这样修了,建议 rebase 时带上。

三、阻塞项:需要 rebase 到 main(v0.2.21)

main 在 PR 基于 08c68d5 之后落了 7 个提交,c96c73e(#106 输出预留)、49aff6f(#107 shadow claim 用固定启发价)、d0a5aa9(#125 tool-pairing 镜像,issue #124)与本 PR 有实质交叉。GitHub 现在报 mergeable_state=dirty(floor 2 说的 CLEAN 是当时的状态)。git merge-tree 显示 9 个文件冲突,逐个看过,全部可解且无算法级矛盾:

文件 冲突性质 解法
AGENTS.md module map 两边各加了一行 并集(window.ts 行取 main 的输出预留版,settings.ts / commands.ts 行取 PR 版)
README.md / README.en.md 配置表同一批行两边都改了 逐行合并:保留 PR 的「运行时热调:/acp config」标注 + main 的输出预留扣减说明
docs/README.md 文档索引同位置各加一行 并集(shadow-price 行取 main 的 #103 更新版,settings 行取 PR 新增)
src/index.ts 类字段、windowFor、方法区三处 并集 + 上述第 4 点的 live 门控修正;关键是 main 的 applyReservation/outputCapFor 与 PR 的 onSettingsChanged 并存后,设计决策 9 的四条 reservation 跳过规则(显式 limit / auto=false / 探测失败 / cap≥window)全部保持成立,窗口键变更触发的 windowCache.clear() 也保证预留状态随热改重新解析
package-lock.json 双方都重生成过 以 main 为底跑完整 npm install(不用 --package-lock-only,floor 2 的教训)——结果 175 条目,跨平台 optional deps(@typescript/typescript-* 等 20 个)完整保留,dsh-settings/schemastery 正确加入
dist/*(3 个) 构建产物 解决 src 后重新 npm run build 生成即可

四、试验合并证明(已完成)

我在仓库内 worktrees/tmp-trial-merge(gitignored 临时区)做了 pr-76 × main-local 的完整合并并按上表逐一解决,然后:

即:rebase 成本很低,没有隐藏地雷,唯一需要人做判断的就是上面第 4 点那个词级修改(我已按"投影与探测都走 live 门控"解决)。

五、建议的收尾步骤(merge 由你操作)

  1. 把分支 rebase 到 main@bb9f2f6,按第三表的解法解决冲突(第 4 点的 live 门控修正建议一并带上);
  2. 顺手补 configResetText 的 try/catch(minor 2);
  3. 重新跑 typecheck && test && build,推回分支;
  4. CI 绿后由你合入(按仓库规矩我不代合)。

另注:floor 1 提到的 DSH 0.1.2 settings 动态命名空间(SettingsController.describe())让 phase-3 浏览器卡片的前置门槛解除了,那个可以作为后续独立 PR 跟进,不阻塞本次 phase-1 合入。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants