Repository navigation
Releases: YokosWY/dsh-calibration-tier
Release list
v3.10.1 — 首次发到 npm(含精简行标签修复)
v3.10.1 — 首次发到 npm
改动:包名 dsh-calibration-tier 首次发布,npm i dsh-calibration-tier 可装;GitHub Actions 走 Trusted Publisher,之后免长期 token 发布。
同时带上:3.10.0 的重复调用精简行里,检索档位直接取 route.level、代理取不存在的 label 字段,曾打出「检索 high|代理 undefined」,改走 LABELS 中文映射;clarify-needs / counter-review 两个子技能改为只能显式调用。
v3.10.0 — 重复调用不再重发档位全文
v3.10.0 — 重复调用不再重发档位全文
问题:clarify_tier 每次调用都回整段固定文本(步骤、回执模板、派活说明),一轮里调两三次就是上千 token。
改动:按会话记「上次发过的签名」= mode + level + 对抗 / 检索 / 代理开关。签名不变时只回一行状态;
档位或任一开关变化立即恢复全文。结构化字段与 contract 完全不变,只多一个 sameAsLast: true。
限制:记忆在进程内,重启插件后首次调用仍是全文;跨会话不共享(各会话本来就该看各自的档)。
验收:node --test test/*.test.mjs 185/185;新增 1 项(首次全文 / 重复精简 / 档位变化恢复)。
v3.8.0 — 可移植:能力族扩到 26 条、非聊天模型剔除、四类覆盖键、doctor 自检
问题:代理档的效果依赖作者本机的注册表(北辰 Anthropic/Grok/DeepSeek、本地 Ollama),别人装上后要么模型一律 5 分兜底,要么 grok-imagine-* 这类图像模型混进候选,counter 隔离经常落 unknown。
改了什么
- 能力族 6 → 26 条:claude haiku/通用、gpt-5.6/5/4、codex、gemini-3/通用、glm-5/4、kimi-k3/通用、minimax、qwen3/通用、step、hy4/hy3、deepseek-v4-pro/兜底、grok;未识别仍 5 分,但带
derived标记 - 非聊天模型自动剔除(
NON_CHAT_PATTERN:image/imagine/video/embed/tts/audio/…),models["p/m"].chat可改判 - 覆盖文件四类键:
models(单条分数/窗口/chat)、families(新族,排在内置表前)、exclude(踢出)、providers(免费线);按 mtime 缓存,改完不用重启 npm run doctor [-- --home=… --main=provider/model]:注册表快照 × 当前能力表 → 每条 route 的族/档/分值、两档实挑与隔离原因、剔除项、未识别项mainRouteFromExec兼容多种宿主形状,主模型读不到时不再一律unknown/low- README 新增「换台机器 / 别人用(同效复现)」:三步、覆盖示例、同效四条前提
验收:node --test test/*.test.mjs 174/174;本机 doctor 实测 13 条快照 → 剔除 2 条图像模型、11 条参与打分,性能档 executor/research=opus、counter=deepseek-v4-pro(high)。
边界:插件不读凭据、不联网、不自带模型;「同效」仍取决于对方注册表里至少有异族 provider(否则隔离只能 mid/low)。
v3.7.2 — 修全量测试并发 flaky:host.test.mjs 不再写死端口
v3.7.2 — 修全量测试并发 flaky:host.test.mjs 不再写死端口
现象:npm test 单跑全绿,但两个进程同时跑(两个会话各跑一次、或本地 CI 与开发并行)时,test/host.test.mjs 会整块 39 项变红。
根因:用例把 DSH_CLARIFY_TIER_PORT 写死成 43991 并占住它,再断言桥接退到 43992。两个进程抢同一对端口时,抢输的一方要么占不到 43991,要么桥接落到 43993,于是永远等不到 :43992 的「桥接就绪」。
改了什么
- 端口不再写死:OS 分配空闲端口(
listen(0))并先占住,再把它告诉插件;桥接往上扫一格绑port+1 - 真绑上的端口从「桥接就绪」日志解析,
BASE/openStream/ 就绪断言都用实测端口,不假设 - 启动前确认
port+1空闲;贴 65535 上限时换端口重试
验收:旧 HEAD 双跑可稳定复现(129 项 / 1 fail);修后双跑两轮 + 三跑并发一轮,6 份结果全部 167/167;npm run verify 167/167。
发布面:只有测试文件变化,插件行为与默认端口(43871..43880)不变。
v3.7.1 — 回执按需出
v3.7.1 — 回执按需出:没发生就不写,别硬凑「0 孩子 / 0 条」
背景:3.7.0 把五模式都做成「清单 + 落盘 + 收尾回执」后,每轮交付固定多出 4~6 行回执;代理没派活也写「性能 · 0 孩子」、对抗没提条目也写「0 条」,噪声反过来盖住结论。
改了什么
renderContract()支持receiptWhen:渲染成「收尾仅在<条件>时单起一行『…』;没发生就不写这行」- 循环 high/max:仅当本轮真跑到 ≥2 轮;代理两档:仅当本轮真派了子代理(children ≥1);对抗:仅当本轮真提出 ≥1 条对抗条目
- 检索增量/全量保持无条件(切档即执行),仍用「收尾必须」,数字须与
tmp\skill-scan*.md对齐 - 三处
steps删掉重复的「收尾单起一行『X 回执:…』」;效率档补一条挑模型步骤,仍 4 步 - 检索格 / 代理格悬停 title 同步为条件口径
限制:receiptWhen 由模型自行判断是否满足,工具侧不做拦截;想机器核对条目数仍用 verify_claims(kind=ledger)。
v3.7.0 — 性能档同级备选 + 五模式统一可执行清单(含 3.6.0 检索清单化)
本版包含未单独发布的 3.6.0(检索档位变成可执行清单;代理侧补并行判据与降级链),下面两节一起说明。
v3.7.0 — 性能档补同级备选:opus 不可用时先退 sonnet;五模式统一可执行清单
背景:性能档此前只有一条主 route(claude-opus-5-5)。opus 一旦限流或请求失败,降级链的第一跳直接是官方 deepseek 效率档——质量落差两档,等于「性能档静默降级成效率档」。用户口径:「给性能档加备选(例如 opus 限流时退到 sonnet)」。
改了什么
- 新增
nearPeers()(lib/agents.js):按当前档的比较口径排序,领域分不低于主 route 减spread(默认 2,覆盖 opus→sonnet 的 1 分差),默认只在同一 provider 内找兄弟模型——同 key 同端点换模型才真能救「这个模型限流/挂了」;跨 provider 交给官方兜底 buildFallbackChain()顺序改为:性能档同级次优(非官方)→ 官方同域同档 → 官方放宽 → 主模型;新增module参数(默认executor)。效率档不插同级备选,避免「名为效率、实为升级」- 启动期预检失败同样先试同级(
opus预检挂了先试sonnet),同 provider 无兄弟才退官方;换模型时推理等级按新模型的efforts重算(effortFor) - 运行期
fallbacks数组随之把sonnet排在官方之前,按链重派即可
同版本第二项:其余四个模式也补上可执行清单
背景:v3.6.0 只给「检索」补了步骤、落盘与回执,思考 / 循环 / 对抗 / 代理仍是一句口径——切了档看不出要做什么,事后也验不出做没做。
lib/tools.js新增renderContract():五模式统一按「头 → 编号步骤 → 提问口径 → 产出/落盘 → 收尾回执 → 守卫」渲染,差异只来自lib/core.js的档位数据;RECEIPT_FIELDS从 4 个占位符扩到 20 个- 思考严格 5 步、极致 7 步(设计树、逆向三条、对抗自检、止损线),极致落
tmp\tier-plan-<YYYYMMDD>.md;循环三档 2/4/5 步,交付与极致分别落tmp\forge-*.md;对抗开着才发步骤与「对抗回执」(三态收口);代理效率 4 步、性能 5 步 test/contract.test.mjs7 项守渲染顺序与五模式结构
限制
- 同级备选只在「同 provider 且领域分差 ≤2」时成立;registry 里没有兄弟模型(例如只配了 opus 一个)时行为与 3.6.0 完全一致
- 不改变 allowedModels 白名单语义:要真正可派,
sonnet仍需在该会话的allowedModels里(agent_delegate走 provider 层不受此限) - 清单是写给模型的口径,不是硬门禁:没落盘时宿主不拦,只能靠回执里的文件名与条目数对照
回执可机械核对(同版本):verify_claims 新增 kind=ledger——读回执对应的落盘文件,数 Markdown 表格数据行,跟回执里的「N 候选」对账(expect.candidates 相等 / expect.min 下限 / 不给期望值只报数)。此前回执靠模型自觉,现在回执说 8 条、文件只有 3 行时,工具直接判未核。
客户端拆片(同版本):lib/client.js 1072 行按职责切成 lib/client/ 六个分片,scripts/build-client.mjs 拼回单文件(浏览器模块只能一个 id 一个文件,发布面不变)。npm run build:client 生成、verify 前置 --check、consistency.test.mjs 守「分片拼接 == lib/client.js」,避免只改分片忘了 build。切片逐字节等价(42790 字节、0 行差异)。
v3.6.0 — 检索档位变成可执行清单;代理侧补并行判据与降级链
背景:检索档位此前只有一句口径(「联网找已装之外能用的技能,只读文本不安装」),切到增量/全量后模型看不出要做什么、事后也验不出做没做——用户口径:「增强检索质量,这个模式每次都没什么存在感」。
改了什么
ROUTE_PLAN每档新增steps(编号 4~5 步)、ledger(必交落盘文件)、receipt(回执模板),旧字段原样保留,老会话状态无需迁移- 增量:
skillq本地盘点 → ≤3 组英文同义词联网查 → 候选表落tmp\skill-scan-<YYYYMMDD>.md(名 / 来源 / 是否已装 / 星数 / 一句用途)→ 装 ≤1 或「不装」给理由 - 全量:中英各 ≥2 组本地盘点 → ≥5 组查询、候选 ≥20 → 同组 ≥2 才比规格 → 判别卡(三段)+ 安装清单 + 冲突清单落
tmp\skill-scan-full-<YYYYMMDD>.md routeLine()输出多行清单,末段硬性要求回复末尾单起一行「检索回执:…」,数字须与落盘文件一致;每档guard补「未落盘 = 未执行」- 检索格悬停 title 同步为「产出 + 落盘 + 回执」摘要(client 兜底同字)
并行判据(lib/fanout.js):代理开着时 agentSection() 的说明末尾多一行「并行:<=N 块;先过依赖图与验收断言,净值 <=0 就别拆;回传只给摘要;赛马不省时」,返回值多 fanout(maxBlocks + 六条 rules + 三条 never)。N 取该档 maxChildren:效率 2、性能 3。净值为 Gain = n*t - (ceil(n/p)*0.6t + beta*t),beta ≥ n-0.6 必亏;三条不拆:赛马取快/投票、同一文件两路并行写、块之间靠同一中间文件互等。判据来源 token-governance/docs/fanout-criteria.md;实测子代理 3.0s/步 vs 主会话 4.8s/步(近 10 天 80 会话,step/start→step/end 配对)。代理关时早退,零注入。
降级链(lib/delegate.js):buildFallbackChain() 让启动期与运行期共用一份有序候选——官方同域同档 → 官方放宽(不限域/档位)→ 主模型,去重且排除当前 route;重试统一落回 spawn。返回值新增 fallbacks(有序数组),fallbackRoute 保留为链首。修掉旧断层:原来「已在官方 deepseek 且启动失败」直接 throw,不再往下退;现在沿链逐条试,全挂才抛最后一次错误(tried 列表进 note)。
自查补的三处
- 官方兜底可能返回主模型:
pickRoute走效率档时,池里挑不到「比基线更强」的会退回基线 route,于是「官方池」里可能拿回自配/主模型,被降级链当第一跳。新增inPool()只承认传进去的那份候选,越界一律落pool[0]。 - 回退时的推理等级:改成
effortFor(cand, preferred)——目标没声明efforts就不传(v3.2.1 口径),声明了但当前值不在列表里就改用它的默认档。 - 运行期链跳过启动期已失败的候选:
buildFallbackChain(..., skip)收一份failedAtStart,避免重派回刚失败过的死路;note 补「隔离度降为 none」。检索侧则在plan缺ledger时不再输出空落盘路径。
修:工具输出含 undefined 被宿主判 not lossless JSON。agentSection() 里 mainRoute: main.provider ? main : undefined,当 exec.agent.model 读不到时该键值即 undefined → 序列化丢键、回读不等价 → clarify_tier 直接 INVALID_TOOL_OUTPUT。改成条件展开 ...(main.provider && main.model ? { mainRoute: main } : {})。代理开着时必现,关着不触发。
限制:回执靠模型自觉执行,工具侧只给清单与判据,不做自动拦截;增量档每轮多 3 次搜索与 1 次写盘,全量更贵,默认仍是「本地」。并行判据同样只是说明与字段,派不派活仍由模型自己判断。
v3.5.0 — 检索/代理收成一格(含 3.4.0 代理=强化)
本版包含未单独发布的 3.4.0(代理 = 强化开关),下面两节一起说明。
v3.5.0 — 检索 / 代理各收成一个轮换格
背景:主条最宽时有 14 个节点(检索开关 + 增量/全量 + 三档 + 循环 + 对抗 + 代理开关 + 效率/性能),窄屏还得降级成一格轮换,两套形态各写一遍测试。用户口径:选项格少一点,一个格子点着切;两个开关挪到选项条最后;「本地 / 默认」也要保持颜色。
改了什么
- 主条固定 11 节点:
常规 严格 极致 ‖ 循环 对抗 ‖ [检索格] [代理格],节点数不再随开关增减 - 两个轮换格挪到末尾(三档 → 循环 → 对抗 → 检索 → 代理)
- 检索格轮换 本地 → 增量 → 全量 → 本地;「本地」=
route.on=false,只做显示名,不进ROUTE_LEVELS/ROUTE_PLAN - 代理格轮换 默认 → 效率 → 性能 → 默认;「默认」=
agent.on=false - 两格恒亮:检索三档恒天蓝、代理三档恒墨绿;
data-on/data-route/data-agent只表状态,不再控制配色(选择器.dct-cell.dct-routecell0,4,0 压过通用选中规则) - 代理色改墨绿:
--dct-agent#b06fd0→#24543f(白字对比 ≈8.7,比三档更深,靠明度差与循环雾绿#66ae7c分开),内描边同步rgba(36,84,63,.45) - 删
WIDE_MIN、data-agent-compact与宽窄屏两套形态 - 轮换只提交变化的一维(档位没变只提交
on);从「本地」出发固定落到增量档 routePlan(false, …)的label改为「本地」,与界面一致- 状态模型与 SCHEMA 9 不变,老状态文件不用迁移
限制:轮换格只看得到当前值和下一档,要直接跳到第三档得点两下;两格恒亮后颜色不再表示开/关(「本地」与「全量」同色),开/关只能看文字——这是「保持颜色渲染」的代价,要恢复灭灯式区分只需把 CSS 里的 data-on 门控加回两条规则。
v3.4.0 — 代理 = 强化开关
语义:代理开关管的是「要不要强化」。关 = 不强化,派活沿用主模型;开 = 强化,再选强度:效率要「比原本强、但只强一档且挑便宜的」,性能要「绝对质量」,用在用户明确在意的任务上。
改了什么
agent_delegate:代理关时不挑 route,直接用主模型的 provider/model(source: "baseline");拿不到主模型信息才退回效率档并在文本里说明- 效率档:候选只留分数严格高于基线的 → 挑档位最低的一档 → 同档分最高 → 同分按
cost取代价低 - 性能档:全池领域分最高 + 模型声明的最高推理等级
- 新增
cost相对代价序(1 最便宜 / 5 最贵;claude-opus5、grok4、claude-sonnet|fable3、deepseek-v4|flash1、未知 3),可逐条覆盖;宿主拿不到真实价格,只能人工排序 - 效率档推理等级回到模型默认档(不再砍到底)
限制:cost 是人工基线,会过期;基线已是注册表上限时效率档如实标 upgraded:false 并沿用基线,不再假装升级。
v3.3.0 — 免费线名单可配(含 3.2.2 404 修复)
本版包含 v2.3.0 之后的全部修复:3.2.2(404)→ 3.2.3(免费线降权)→ 3.3.0(名单可配 + 文档守卫)。
3.3.0
背景:v3.2.3 起免费线在同分时降权,但名单是写死在 lib/core.js 的 —— 装了新的免费额度插件,就得改代码等发版。
改了什么
- 名单改为「内置默认 + 配置文件覆盖」:
~/.dsh/storages/calibration-models.json{ "providers": { "buddy": false, "my-free-channel": true } }false摘掉内置项、true加新渠道;与models能力覆盖共用同一份文件 - 名单按文件
mtime+size缓存,改完下一个请求即生效,不用重启;单项free仍优先于名单
为什么不自动识别:宿主 llm 的 provider/model 信息里没有任何价格或免费标记(LlmProviderInfo 只有 id/name),做不到自动判定。
3.2.3
现象:效率档自动挑到 buddy/deepseek-v4-flash(第三方插件的 WorkBuddy 免费线),子代理启动成功,运行中静默失败,没有任何收尾消息。
根因:不是能力分低——deepseek-v4-flash 与官方同族同分(8)。同分的 tie-break 是 provider:model 字典序,buddy 排最前,于是免费线赢过官方。
改了什么
scoreRoute给免费线打free标记(名单见lib/core.js的FREE_LINE_PROVIDERS)better()在同分时把免费线排后:能力分更高照样能选中,不是封杀;手动点名(provider + model)不受影响calibration-models.json里{ models: { "provider/model": { free: true|false } } }可单条覆盖
限制:插件在进程启动时加载,升级后需重启 DSH;名单是静态约定,新出现的免费线要手工补进去。
3.2.2
现象:agent_delegate 启动 yokos-beichenapi-anthropic/claude-opus-5-5 成功,但子代理运行即失败(404 page not found,无任何提示)。
根因:profile 里该 provider 的 baseURL 写成 https://api.beichenapi.com/v1,而适配器会再拼 /v1/messages → 实际请求 /v1/v1/messages。
实测:/v1/messages 返回 401(路径对、只缺 key),/v1/v1/messages 返回 404。
改了什么
baseURL改成https://api.beichenapi.com(改前备份 profile)agent_delegate返回fallbackRoute:运行期失败时主模型直接拿它重派官方,并告知「自配失败,已用官方兜底」
限制:预检只保证配置可解析,不保证网络连通;运行期失败只能靠 fallbackRoute 重派,工具自己不会等待子代理结果。
v2.3.0 — 思考强度落到清单:歧义点 / 覆盖轴 / 逆向
v2.3.0 — 思考强度落到清单:歧义点 / 覆盖轴 / 逆向
改了什么:clarify_tier 不再只回一个档名,而是随档位发三张清单,模型据此决定「问什么、看多全、怎么反推」。
三张清单:
- 歧义点(严格 2 条 / 极致 3 条):目标与验收能不能一句话说清;不可逆与外部动作(推送 / 发布 / 改设置 / 删除)谁批准、怎么回滚;范围与取舍(不做什么、代价是什么)。只有答案会改变执行的才弹窗问,能自己查证的不占提问额度。
- 覆盖轴(严格 3 条 / 极致 6 条):正常路径、边界与空值、失败与回滚;极致再加依赖与副作用、成本与性能、后续与可维护。逐轴一句结论,未涉及的写「Z」。
- 逆向(严格 1 条 / 极致 3 条):pre-mortem(假设已失败,倒推原因);极致再加反证(什么证据会推翻结论)与反例(触发条件 / 后果 / 检查方法)。
循环模式不再短路:此前循环档固定返回 tier: "off"、工具文案写「不叠加思考档」,于是循环档里从不提问——2.2.1 的 GitHub About 带着「一框三模式」发了两版没人发现,就是这条的直接后果。现在轻量 / 交付 / 极致 同档位映射成 常规 / 严格 / 极致,think.source 标 loop;forge_level 同样带 think。
范围:状态 schema、/state 字段、客户端节点与配色都没变;变的是两个工具的返回结构与文案。think 里 probes / axes / reverse 是可执行清单,confirm 是要报的确认点个数,ask 是提问口径。新增 3 项测试,共 86 项。
v2.2.1 — 循环模式下「检索」恒天蓝
v2.2.1 — 循环模式下「检索」恒天蓝
改了什么:检索 开关和它展开的三格(本地 / 增量 / 全量)不再跟着模式换色——思考、循环都是天蓝 #3a9ad9。循环开关仍绿、对抗开关仍红;循环 + 对抗同开时只有等级条转橙。
为什么坏:循环的换色规则原先写通用选择器 .dct-cell[data-on='1']:not(.dct-counter)(特异性 0,5,0),压过检索的 .dct-routecell / .dct-route-toggle(0,3,0)——只要在循环模式,检索那两处也被染绿。使用说明与 README 写的却是「检索常驻天蓝」,实现和文档不一致。
改法:循环换色收窄成 .dct-cell[data-level][data-on='1'],只认等级条。收窄后循环格原先靠这条通用规则显绿,它自己的 .dct-mode[data-on='1'](0,2,0)会输给紫(0,3,0)而变紫,所以升到 .dct-root .dct-cell.dct-mode[data-on='1'](0,4,0)——与源序无关,不再靠「先写谁」。
范围:纯前端样式。状态 schema、/state 字段、clarify_tier / forge_level 返回值、DOM 节点与文案都没变。四态取色用 headless Chrome 核对:循环=绿、检索=天蓝、循环+对抗同开=橙绿红蓝四色并存、思考=紫+天蓝。新增 1 项守卫测试,共 81 项。