Repository navigation
[PR] feat: local JSON announcements lane — validator, targeting gates, hash-dismiss (#5548 P2) - #5561
ranxianglei wants to merge 3 commits into
Conversation
…rer (lane A, #5548 P1) Part of #5548 (approved unified announcement panel design, phase 1 of 4). Converge the hand-copied panel banners (pck-default-off #5079, wm-fastpath-intro #5469) into one registry (src/notices.ts) with a shared record schema, kind-priority/tone/dismiss-mode pure functions, and one client render loop (textContent only, max 5 header banners + overflow list card). Overview payload now carries a unified notices array; new GET /__bili/notices endpoint. Dismissal store, endpoint and allowlist semantics preserved (allowlist widened to registered dynamic ids for lanes B/C). No config surface change.
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g billion-context@0.0.7917-pr.5561.f61d400This exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr5561.tgz
npm install -g packageInstall instructions are refreshed on each push. |
…ts gate The #5548 P2 lane exported eight declarations referenced only within their own modules (notices.ts: NoticeTone/NoticeDismiss/NoticeText/BuiltInContext/ BuiltinNotice/VisibleNoticesOptions; local-announcements.ts: ANNOUNCEMENTS_DIRNAME/ LocalAnnouncementLoad), which failed the check-unused-exports static gate on #5561's head. Drop the leading `export` from each; they stay module-internal. No behavior change — re-export when a later phase (lane C / public validator API) actually consumes them by name. Verified locally: unused-exports gate clean, tsc --noEmit clean, 52/52 targeted notice/pck/wm/i18n tests pass.
(ai: vllm-qwen/qwen3.8-27b) PR #5561(#5548 P2)审核结论:可合并 —— 前提是先合 P1 #5557。 方向对、实现干净、测试有牙、无回归;我顺手修掉一个 CI 红灯(unused-exports)并已推到分支。 我做了什么
结构化八问
非阻塞观察(供你判断,均不卡合并)
判定P2 本身质量达标、无阻塞缺陷;CI 的 unused-exports 我已修掉推上去。待办只剩一件:先合 P1 #5557,再把本 PR rebase 到合入后的 P1 之上即可合并(本 PR 叠在尚未合入的 P1 上)。其余观察项均为可选优化,不卡合并。 |
|
(ai: vllm-qwen/qwen3.8-27b) 关系备注(重复判定):PR #5570(branch 独立审核在 #5570 head 确认了 4 处已验证缺陷(persistent-dismiss 端点缺口 + caret 测试期望与标准 semver 矛盾 + TS2345×2 + unused-exports×5),明细见 #5570 的审核评论。本 PR 对应实现(服务端按 id 找回记录后推导 dismiss 哈希键)不受影响。系列取舍(X 系 vs Y 系)已在 #5570 线程提交决策请求。 |
(ai: vllm-qwen/qwen3.8-27b) 收到。我把 git 图拉出来核了一遍——重复是「系列级」的,不止一个 P2。先给结论:同意保留本 PR(#5561,先到),#5570 维持 duplicate(我不关,关单归你)。但真正要拍板的是「留哪条系列线」,这点已在 #5570 线程立了决策请求,我不越线替代它。 git 证据(我实测)两条系列都从同一个 v0.1.212 提交
两系各自独立实现了同一套「统一公告注册表」(src/notices.ts + admin.ts + web client/i18n/page),还各自撞了同一个 unused-exports 门并各自修了(A: 给决策补一个事实A 系是更完整的线:P1→P2→P3→P4 四段都已切出分支、footprint 更大、有专门 banner 测试;B 系目前只有 P1+P2,且其 P2(#5570)按它自己的审核带 4 处已验证缺陷。若按先来后到保留 A 系(即本 PR),则 #5554(B-P1)、#5570(B-P2) 都应让位;反之留 B 系则本 PR 需弃。取舍仍归 #5570 线程的决策请求。 对本 PR(#5561)的一个具体提醒
|
🔶 需要决策 结论先行:本 PR 与 master 的冲突不是机械冲突,而是「公告子系统两套不兼容实现」的设计分叉,无法用「取并集」式 rebase 安全解决。任何自动 force-push 都会二选一踩雷——要么覆盖已上线的简单注册表并回退 11-09 上线的 iot-thinking 提示,要么产出不编译的混合体。故停手,请你拍板方向。 我查证到的事实(全部本地 git 实测,非猜测)
三个选项(逐选项影响/风险见下方八问第 3、5 问)
结构化八问(决策请求)
选项对比表
推荐:B。 若超时未决的安全默认:保持本 PR 原样不动(不 force-push 任何猜测性解法),冲突维持 dirty;由你在 B(推荐)/C 间定向后我再执行——因为自动动作在此处必然踩到「回退线上 iot-thinking」或「推出不编译分支」二者之一,宁可停手。 (本次我未动分支、未 push、未改 PR 正文;已按规则打上 needs-decision 标签。) |
[ework] CI fix verified green ✓ |
1 similar comment
[ework] CI fix verified green ✓ |
🔶 需要决策 第 2 次触发 · live 复核:状态无变化,仍等你拍板。 本轮按 status-freshness 重新拉了 live git(非凭记忆),结论与昨天 floor 12 完全一致——仍是「同一文件两套不兼容公告实现」的设计分叉,未收到你的 A/B/C 定向。 本轮复核到的 live 事实(本地 git 实测):
所以: 任何自动 rebase 都只能二选一踩雷——要么覆盖已上线注册表并回退 11-09 上线的 iot-thinking 提示,要么产出不编译的混合体。完整选项 / 八问 / 对比表见 floor 12,此处不重复贴。 仍需你拍板(回一个字母即可):
超时安全默认:保持本 PR 原样不动——我不推任何猜测性解法,等你定向后再执行。 (needs-decision 标签已在位;本轮未 push、未改分支、未动 PR 正文。) |
[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b) CI 自动修车道第 2 次触发 — 本轮结论:仍是设计分叉,无机械解法,等你拍板。 本轮我做了什么(全部 live 复核,非凭记忆):
为什么不能自动解:同一文件两套不兼容公告实现,任何 force-push 要么回退 11-09 上线的 iot-thinking 提示、要么产出不编译分支。完整选项 / 八问 / 对比表见 floor 12。 请回一个字母:A / B / C。 推荐 B(保留 master 现状、把 P2 重做到上面,新 PR 而非 rebase 本分支);超时安全默认 = 保持本 PR 原样不动。你定向后我立即执行。 结构化八问(本次运行)
判定:维持挂起,等你 A/B/C 定向。 |
[ework] CI fix verified green ✓ |
[bot] 🏷 🔶 需要决策 (ai: vllm-qwen/qwen3.8-27b) 3rd auto-trigger (~30 min after my last two notes). Re-verified live this run — state is byte-for-byte unchanged and no owner A/B/C direction has arrived (floors 21–25 are all system markers: completed badges + a "CI fix verified green" marker + this run's processing badge). What I checked (local git, live):
The conflict remains a two-incompatible-implementations design fork of Please pick A / B / C. Recommendation B (keep master's shipped registry, rework P2 onto it as a new PR); safe default if undecided = leave this PR untouched. I'll execute immediately on your call. 八问(本轮)无代码改动、live 状态与前两次逐项一致——各项均「不涉及 / 未变」;完整八问见 floor 12 / 22。 |
[ework] CI fix verified green ✓ |
1 similar comment
[ework] CI fix verified green ✓ |
[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b) 4th auto-fix trigger — re-verified live this run; state unchanged, still blocked on your decision. I re-ran the live git check instead of trusting memory. One thing did move, and it does not help: master advanced ~28 commits (true tip now
So this remains a design fork, not a mechanical conflict: any rebase either overwrites master's shipped Still awaiting your pick (full options + comparison table at floor 12, restated at 20 & 22):
Safe default if undecided: leave the PR untouched (no speculative force-push). 中文八问(结论未变,完整选项表见 floor 12):
判定:维持 |
[ework] CI fix verified green ✓ |
(ai: vllm-qwen/qwen3.8-27b)
Part of #5548 (unified announcement panel, design v2 approved) — phase 2 of 4. Phase 1 is #5557 (built-in registry + single renderer); this branch is stacked on it, so merge #5557 first.
What this adds
Lane B of the three-source design: user-owned announcement files under
~/.config/billion-context/announcements/*.json(one validated record per file) merge into the samenotices[]payload as built-ins, with B overriding A on id collision. Everything ships behind the shared pure machinery insrc/notices.ts:validateNoticeRecord): unknown fields dropped + debug-logged, bad value kills only that record. Full field contract: id regex, kind enum, multilang text limits (title ≤120 / desc ≤600 / hint ≤300 per locale), ctaUrl http(s) ≤200, tone/dismiss enums, priority/percent int 0–100|null, ISO8601 timestamps.0.1.212), comparator lists (>=a <b,^x.y.z), interval lists ([>=a <b] || [c d]); elements AND together; dirty pre-release versions compare by numeric body; unparseable local version hides gated records (宁缺毋滥).sha256(installId|id) % 100against a stable persisted install id (newinstall-idfile under the state dir; unpersistable → gated records hide instead of flickering).id→id@sha16(normalized record)so a content edit re-shows the banner once; legacy bare-id entries still honored (an upgrade never re-shows an already-closed banner). Store becomes insertion-order FIFO capped at 200 keys. Newdismissmodes land:instance(process-memory only, re-shows on restart) andalways(never hidden, no close button rendered — client side already shipped in P1).src/local-announcements.ts): one record per*.jsonfile, 64 KB/file cap before parse, per-file skip+warn (a broken file never takes down the rest or the page), memoized on name:size:mtime signature so warn logs fire once per change.Behavior changes (old → new, why)
upgrade-notices.json) keys: bareid→id@sha16(record)for persistent dismissals. Legacy bare entries remain honored. Why: content-edited banners must re-show once (§4.4) while upgrades must not resurrect closed ones.<stateDir>/install-id(random uuid, created on first run). Why: deterministic per-install percent buckets. Read-only state dir → empty id → percent-gated records hidden.~/.config/billion-context/announcements/(owner-approved design point, confirmation fix: address all code review findings (condense, routing, session-id, dead code) #2 in Unified Announcement Panel Design (Approved): Built-in declarations + local JSON + remote GitHub raw — a single renderer | 公告面统一设计(已批准):内置声明 + 本地 JSON + 远程 GitHub raw,三来源一套渲染器 #5548). No env var in this phase (BILI_ANNOUNCEMENTS_URLis phase 3); CONFIGURATION.md docs land in phase 4.POST /__bili/notices/dismissgains mode-aware behavior (instance = memory-only; always = 200 without writing). Built-ins are allpersistent, so existing banners behave exactly as before.No kernel change, no wire involvement, built-in banner copy/tones byte-stable (covered by P1 tests, re-run green).
Verification
Targeted suites (local; full verdict = CI):
tests/notices-local-lane.test.ts(new, 23 tests: validator matrix, matcher forms incl. caret bounds, percent determinism + boundaries, time-window edges, hash canonicalization, layer merge, loader incl. bad-JSON/oversize/unknown-field negatives, FIFO cap, both dismiss-key forms) +tests/notices-registry.test.ts+tests/issue5079-pck-default-off.test.ts+tests/wm-fastpath-intro-notice.test.ts+tests/web-i18n.test.ts= 52/52 pass;npm run typecheckclean;npm run buildOK.Exit criteria from §七: drop-a-file→shows (loader test picks up a newly written file without restart — stronger than required) ✓; negative suite 坏JSON / 版本不命中 / 百分比未中窗 / 过期 ✓; always-no-button (P1 client test) ✓; instance-restart-reshow ✓.
八问
~/.config/billion-context/announcements/(owner 已批准的设计点 2,P4 补文档);新增状态文件<stateDir>/install-id(机器生成,非用户配置);本阶段无新 env。