Skip to content

fix: growth scale-flip reset, per-location auto-update, panel denominator - #268

Merged
ranxianglei merged 1 commit into
masterfrom
2026-09-01_fix-growth-scale-and-auto-updater
Sep 7, 2026
Merged

fix: growth scale-flip reset, per-location auto-update, panel denominator#268
ranxianglei merged 1 commit into
masterfrom
2026-09-01_fix-growth-scale-and-auto-updater

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Fixes #267 (three related issues).

1. Growth baseline mixed two scales (main)

tokenCount runs on the estimate scale (chars/4) while the usage anchor is stale, and on the provider scale when it is fresh. A growth delta spanning that switch was a false artifact — e.g. 48k (provider) − 12.5k (estimate) ≈ 35k "growth" right after a compress, even though the context shrank.

The context transform now tracks the per-session anchor scale (runtime.noteTokenScale) and re-anchors the growth baseline (lastNudgeShownTokens + lastPerMessageNudgeTokens) on a flip, so growth only accumulates same-source deltas. The 0.75/0.95 usage bands keep the floor-stale behavior untouched — PR #258's stale-anchor guard is preserved (tests/sent-view-arbitration.test.ts still green).

Note: I did not take the "always use Math.max(sent, providerReal)" option from the issue, because it would break the stale-anchor guard (the post-compress first nudge would false-trigger emergency from the pre-compress high value). The "growth only accumulates same-source deltas" option is the one that keeps both behaviors correct.

2. Auto-updater looped on a read-only global install, failed invisibly

  • The check throttle file was shared across every installed copy, so a healthy copy refreshed it and silently suppressed a failing copy's checks; the failing copy then retried the EACCES install forever with no user-visible notice.
  • The throttle and a new stop-retry marker are now keyed per install location (locationKey), so copies don't suppress each other.
  • A permission failure (EACCES/EPERM/…) marks the location read-only and stops retrying, and a one-time hint tells the user to run npm i -g billion-context-pi (or remove the global copy).
  • Documented the read-only behavior + the two parallel update mechanisms (extension auto-update vs pi core banner) in CONFIGURATION.md / .zh-CN.md.

3. Panel percentages used the wrong denominator

/acp and acp_status measured every percentage against the full window, while the nudge bands run against (window − output headroom). They now apply the same applyOutputHeadroom reservation as the live context transform (extracted into a shared helper), so every percentage is measured against the same real request limit.

Tests

  • tests/growth-scale-flip.test.ts (new): baseline re-anchors on the stale→not-stale flip; no spurious reset when the scale is stable.
  • tests/update.test.ts: EACCES → read-only outcome + marker; non-permission failure → no marker; marker present → check skipped + notify once per process.
  • Full suite: 467 pass.

Note: the panel copy items from #267 ("never shrinks; includes compressed originals" and the cumulative "tokens compressed" label) live in acp-kernel's panel renderer and need an acp-kernel change + release — tracked separately.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

📦 Built Extension Artifact

Branch: 2026-09-01_fix-growth-scale-and-auto-updater (c8baad0)

Option A — Install from npm PR tag (recommended)

pi install npm:billion-context-pi@pr-268

Each push to this PR publishes a new version under the pr-268 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pi-pr268.tgz
pi install ./package

This comment is automatically updated on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 收到,PR #268 已接手跟踪。当前状态:

  • 单 commit dff317f(fix: growth scale-flip reset, per-location auto-update, panel denominator)
  • CI:pr-validation / build-artifact / docker / e2e (ubuntu) / test (ubuntu 22+24) 均已 ✅;test (windows 22+24)e2e (windows) 还在跑
  • 我正在本地 checkout PR 分支复跑 typecheck + 全量测试,确认 467 pass 与 PR 描述一致

Windows CI 跑完后我回来汇报最终结果。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 ✅ 验证完成,PR #268 可以合并。

CI(head dff317f,9/9 全绿)

  • pr-validation / build-artifact / docker
  • test (ubuntu 22+24) / test (windows 22+24)
  • e2e (ubuntu) / e2e (windows)

本地复跑(PR 分支)

  • npm run typecheck
  • npm test:467 pass / 0 fail / 3 skipped —— 与 PR 描述一致(含新增 tests/growth-scale-flip.test.ts 2 个 + tests/update.test.ts 3 个)
  • npm run build ✅(dist 545KB,acp-kernel 正常内联)

代码审查要点

  1. Growth scale-flip resetruntime.noteTokenScale(sid, anchorStale) 按 session 跟踪刻度,翻转时把 lastNudgeShownTokens + lastPerMessageNudgeTokens 归零。我核对了 acp-kernel decideNudgegrowthReference 回退链(lastNudgeShownTokens > 0 ? … : baseline > 0 ? baseline : tokenCount)——两者归零后 reference 回退到 tokenCount,growth = 0,不会误触 growth nudge;hadPendingNudge 也随之正确失效。usage 档位(0.75/0.95)的 floor-stale 路径未动,sent-view-arbitration.test.ts 保持绿。
  2. Auto-updater:throttle + read-only marker 都按 locationKey(sha256 前 12 位)区分安装位置;PERMISSION_ERROR_RE 匹配 npm stderr(EACCES/EPERM/permission denied/read-only file system)而非退出码;notifyReadOnly 每进程只提示一次,resetUpdateStateForTest 供测试复位。逻辑闭环:标记后 checkForUpdate 直接跳过(不跑 npm view、不重试)。
  3. Panel 分母applyOutputHeadroom 抽成共享 helper,/acp(commands.ts)、acp_status(status-tool.ts)和 live context transform(index.ts)三处统一套用,返回新 config 不污染共享 resolved config,Anthropic 豁免逻辑保留。

状态:无冲突(mergeable: true),无 review 意见。mergeable_state: blocked 是等待人工审批/合并——按规矩 merge 由人来操作:#268

另:#267 里「never shrinks; includes compressed originals」文案和「tokens compressed」cumulative 标注在 acp-kernel 的 panel 渲染器里,需要 acp-kernel 改动 + 发版后再 bump,单独跟踪。

@ranxianglei

Copy link
Copy Markdown
Owner Author

Review + rebase 完成

方案确认:noteTokenScale flip 检测(首观测不触发)+ 重置 growth 基线的思路正确;floor-stale 行为(#258 的 stale-anchor guard)完整保留;per-location 自动更新与面板分母部分 review 无异议。

Review 发现一个实质缺口(已在本次 rebase 中补上):原分支基于 kernel 0.0.50 编写,重置集合只有 lastNudgeShownTokens + lastPerMessageNudgeTokens。kernel 0.0.55(#310 已带)新增了 per-tier cadence 基线 lastShownByTier(types.d.ts NudgeState):cadenceMet = tokenCount - lastShownByTier[tier] >= growthFloor。scale 翻转后旧刻度 lastShown 对新刻度 tokenCount 相减,恰好复现 issue 里的 "+35k 假增长"cadence 旁路。现补 state.nudge.lastShownByTier = {}(翻转到新刻度后重新起算 cadence,与另两个字段的 reset-to-0 语义一致;内核内容就绪门槛防止翻转后立即误触发),并在 growth-scale-flip.test.ts 加了逐 tier 断言。

已 rebase 到 v0.1.58 master(原 base 落后于 #310/#311/#315):

本地验证:growth-scale-flip + update + sent-view-arbitration 32/32 通过(含新增 lastShownByTier 断言),build 通过。CI 重跑中。

合并顺序提醒(跨仓依赖):kernel #182(面板文案)先合并发版,本 PR 后合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 Rebase 后的分支(head cb9d955,base v0.1.58 master)已全面复核完毕。

lastShownByTier 缺口修复 — 确认到位

  • 翻转处理现在重置全部三个基线:lastNudgeShownTokens + lastPerMessageNudgeTokens + lastShownByTier = {}(src/index.ts:310-314)。
  • 守卫位置正确:移到 view-recount([Bug] Token 计数与压缩后状态不同步,导致低收益及零收益的连续压缩 #289)+ armedFloor 之后、最终 tokenCount 确定后;!hostFloorActiveusageAnchorPredatesCompression(entries)(src/index.ts:282),与旧版 stale 判定等价。
  • 对照 acp-kernel 0.0.55 内核语义核实:lastShownByTier[t] 只在 nudge 注入时 stamp(processTurn),cadence 判断为 lastShown === 0 || tokenCount − lastShown[t] >= growthFloor。内核自带一个按幅度触发的 shrink-reset(tokenCount < baseline − growthTokens 时三者归零),但它是阈值相关的;bcp 侧的显式 scale-flip reset 是确定性的同源保证,两者不冲突、语义一致。
  • 新增的逐 tier 断言不是空转:我做了 debug 复跑,turn 2(flip 后,~97% usage 触发 emergency T1 注入)结束状态为 lastShownByTier = {"1": 175000} —— 断言循环实际迭代到 tier "1" 并验证其落在 provider 刻度(≥170K)。若无 flip reset,旧刻度 lastShown 会残留并被新刻度 tokenCount 相减,正是 issue 里的 +35k cadence 旁路。
  • update.ts:per-location throttle/read-only 逻辑已正确移植在 master 的 specUpdateTag/isVersionNewer/dist-tag 追踪之上,签名统一无冲突。

本地验证

  • typecheck ✅;build ✅(acp-kernel 0.0.55 内联正常)
  • 全量测试:首次跑出现 1 个瞬时失败(未捕获到具体用例名),随后 连续 5 次全绿:594 pass / 0 fail / 3 skipped。PR 涉及的文件(growth-scale-flip / update / sent-view-arbitration)每次均通过。该单次失败无法复现、无证据指向本 PR 改动,视为本地环境瞬时 flake,不单独开 issue;若 CI 或后续再出现我会跟进。

CI(cb9d955,9/9 全绿):pr-validation / build-artifact / docker / test (ubuntu 22+24) / test (windows 22+24) / e2e (ubuntu+windows) ✅

PR 状态:open、无冲突(mergeable: true)、无 review 意见;mergeable_state: blocked 等待人工合并——merge 由人来操作:#268

合并顺序已知悉:kernel #182(面板文案)先合并发版,本 PR 随后合并。本分支沿用 master 的 kernel 0.0.55 pin、自身不 bump 版本,所以顺序约束在发版排期层面,理解无误。

@ranxianglei

Copy link
Copy Markdown
Owner Author

这个对应的issue已经关了?这个还需要合并吗

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 查了状态,两个问题分开答:

issue #267 确实已关(2026-09-07 标记 completed),但修复代码并不在 master 里——我核对了 master 当前的 src/index.ts,没有 noteTokenScale/lastShownByTier reset/locationKey,即 #268 的三个修复都还没进主干。关 issue 只是把工单标完成,不会代替合并 PR;如果 #268 不合,这些修复不会随任何版本发布。

所以:还需要合并。 而且现在时机正好——之前约定的前置条件已满足:kernel #182 已发版(0.0.56,master 上经 #318 完成 0.0.55 → 0.0.56 的 bump)。我这就按之前说好的收尾:把 #268 rebase 到新 master(diff 会自动带上 0.0.56 pin)、本地同步依赖后重跑 typecheck/test/build,推上去等 CI。完成后回来说结果,合并由你操作。

@ranxianglei
ranxianglei force-pushed the 2026-09-01_fix-growth-scale-and-auto-updater branch from cb9d955 to 1c9c0db Compare September 7, 2026 01:19
@ranxianglei

Copy link
Copy Markdown
Owner Author

冲突了 解决下

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 收尾完成,#268 已就绪可合并。

Rebase:分支已 rebase 到新 master(d2a89de,含 #318 的 kernel 0.0.55 → 0.0.56),干净应用、无冲突,单 commit 1c9c0db。因为本 PR 的 diff 不碰 package.json,rebase 后自动继承 master 的 acp-kernel 0.0.56 精确 pin(无 ^)+ 同步 lockfile,不需要额外 bump commit——之前说好的"bump 到 #182 发版的新版本"这一步已等效完成。

本地验证(kernel 0.0.56)npm ci 确认安装 0.0.56 → typecheck ✅;全量测试 594 pass / 0 fail / 3 skipped ✅(growth-scale-flip / update / sent-view-arbitration 全过);build ✅(acp-kernel 内联正常,dist 720.53 KB)。

CI(head 1c9c0db,9/9 全绿):pr-validation / build-artifact / docker / test (ubuntu 22+24) / test (windows 22+24) / e2e (ubuntu+windows) ✅

结论:issue #267 虽已关,但修复代码此前不在 master,现在这条分支就是让三个修复真正落主干的最后一步。可以合并了(merge 由你操作):#268

@ranxianglei
ranxianglei force-pushed the 2026-09-01_fix-growth-scale-and-auto-updater branch from 1c9c0db to 3b8f09f Compare September 7, 2026 01:24
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 ework agent · qwen3.8-27b

[bot] 🏷 冲突已解决,分支已 rebase 到最新 master(9e52927,含 #297 proxy stand-down 修复),新 head 3b8f09f

冲突点:只有 src/runtime.ts 一处——#297 往 runtime 返回对象里加了 refusalMessage getter/setter(proxy stand-down 用),本 PR 加了 noteTokenScale, dropTokenScale,两边都改了同一个 return 列表。解法是把两者并集保留;接口声明和函数定义部分 git 已自动合并无误。

语义核对#297standDownIfProxied 在 session lifecycle 和 context transform 入口提前 return(src/index.ts:176、:252),stand-down 时不会走到我们的 scale-flip 逻辑;非 stand-down 路径下本 PR 的守卫(hostFloorActive / noteTokenScale(sid, !hostFloorActive),src/index.ts:308/:336)原样保留,两个功能互不干扰。

验证:typecheck ✅;全量测试 614 pass / 0 fail / 3 skipped ✅(含 #297 新增的 proxy-standdown 20 个用例 + 本 PR 全部用例);build ✅。

CI(head 3b8f09f,9/9 全绿):pr-validation / build-artifact / docker / test (ubuntu 22+24) / test (windows 22+24) / e2e (ubuntu+windows) ✅

现在无冲突、CI 全绿,可以合并了:#268

…ator

Issue #267: three related fixes.

1. Growth baseline mixed two scales (main). tokenCount runs on the
   estimate scale while the usage anchor is stale and on the provider
   scale when it is fresh. A growth delta spanning that switch was a
   false artifact (e.g. 48k provider - 12.5k estimate ~= 35k "growth"
   right after a compress). The context transform now tracks the
   per-session anchor scale and re-anchors the growth baseline
   (lastNudgeShownTokens + lastPerMessageNudgeTokens) on a flip, so
   growth only accumulates same-source deltas. The 0.75/0.95 usage
   bands keep the floor-stale behavior untouched.

2. Auto-updater looped on a read-only global install and failed
   invisibly. The check throttle file was shared across every installed
   copy, so a healthy copy refreshed it and silently suppressed a
   failing copy's checks; the failing copy then retried the EACCES
   install forever with no user-visible notice. The throttle and a new
   stop-retry marker are now keyed per install location, a permission
   failure (EACCES/EPERM) marks the location read-only and stops
   retrying, and a one-time hint tells the user to run `npm i -g`.

3. Panel percentages used the full window as the denominator while the
   nudge bands run against (window - output headroom). /acp and
   acp_status now apply the same output-headroom reservation as the
   live context transform (shared applyOutputHeadroom helper) so every
   percentage is measured against the same real request limit.

Co-Authored-By: ework daemon <daemon@ework.local>

Rebased onto v0.1.58 (kernel 0.0.55):
- keep master update.ts newer specUpdateTag/isVersionNewer/dist-tag tracking and the #289 view-recount structure; port per-location throttle/read-only logic on top
- extend scale-flip reset to lastShownByTier - kernel 0.0.55 per-tier cadence baselines; old-scale lastShown minus new-scale tokenCount re-creates the false +35k growth cadence bypass from #267
@ranxianglei
ranxianglei force-pushed the 2026-09-01_fix-growth-scale-and-auto-updater branch from 3b8f09f to c8baad0 Compare September 7, 2026 02:31
@ranxianglei

Copy link
Copy Markdown
Owner Author

rebase 到 master(#316/#318/#319 合入后)。冲突仅 src/runtime.ts return 对象一行(#316 的 nudge 刻度戳 API vs 本 PR 的 noteTokenScale/dropTokenScale),取并集。

组合语义补强:刻度翻转时原 PR 只重置 kernel 侧基线(lastNudgeShownTokens / lastShownByTier);#316 又引入了扩展侧刻度戳 —— 同轮 re-inject 的增长是 tokenCount - nudgeShownTokensFor(turnKey),旧刻度戳跨翻转相减会伪造满地板增长。现翻转分支同时调用新增的 runtime.clearNudgeTokenStamps()

全套件 620 pass / 0 fail,growth-scale-flip + nudge-reinject 5/5 共同验证。

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.

Growth 基线混用两套刻度

1 participant