Skip to content

[PR] feat: local JSON announcements lane — validator, targeting gates, hash-dismiss (#5548 P2) - #5561

Open
ranxianglei wants to merge 3 commits into
masterfrom
2026-11-02_notices-local-json-p2
Open

ranxianglei wants to merge 3 commits into
masterfrom
2026-11-02_notices-local-json-p2

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

(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 same notices[] payload as built-ins, with B overriding A on id collision. Everything ships behind the shared pure machinery in src/notices.ts:

  • Whitelist validator (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.
  • versions matcher: exact pin (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 (宁缺毋滥).
  • percent bucketing: sha256(installId|id) % 100 against a stable persisted install id (new install-id file under the state dir; unpersistable → gated records hide instead of flickering).
  • since/until window (since inclusive, until exclusive).
  • hash-dismiss (§4.4): persistent store keys upgrade bare 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. New dismiss modes land: instance (process-memory only, re-shows on restart) and always (never hidden, no close button rendered — client side already shipped in P1).
  • Loader (src/local-announcements.ts): one record per *.json file, 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)

  1. Dismissal store (upgrade-notices.json) keys: bare id → 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.
  2. Store array: sorted/unbounded → insertion-order, capped at 200 keys (FIFO eviction). Why: §4.4 cap; order is required for FIFO.
  3. New state file <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.
  4. New user-facing directory ~/.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_URL is phase 3); CONFIGURATION.md docs land in phase 4.
  5. POST /__bili/notices/dismiss gains mode-aware behavior (instance = memory-only; always = 200 without writing). Built-ins are all persistent, 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 typecheck clean; npm run build OK.

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 ✓.

八问

  1. 是什么问题:公告面三期之二——让用户能在本地放 JSON 文件自定义公告,并与内置公告走同一套校验/过滤/渲染。
  2. 什么原因导致的:设计缺口(Unified Announcement Panel Design (Approved): Built-in declarations + local JSON + remote GitHub raw — a single renderer | 公告面统一设计(已批准):内置声明 + 本地 JSON + 远程 GitHub raw,三来源一套渲染器 #5548):此前只有代码内置的三条提示,用户侧无任何自助渠道;本 PR 补上本地文件车道与全部 targeting/校验机制。
  3. 影响范围与严重程度:新增能力,默认零影响(目录不存在 = 零记录);既有两条内置横幅行为逐字节不变(P1 测试复跑绿)。严重程度:不涉及(非缺陷修复)。
  4. 怎么修复的:纯函数层(校验器/版本匹配器/分桶/时间窗/hash-dismiss/分层合并)放在 notices.ts,fs 只存在于两个薄模块(install-id、local-announcements),服务端 collectVisibleNotices 一处汇聚三来源。
  5. 是否有回归问题:逐项过——dismiss 存储文件格式不变(键升级为超集兼容,旧裸 id 仍生效,升级不会让已关横幅复活);存储从排序无上限改为插入序 200 上限(FIFO 淘汰最旧,正常用量远触不到);pckNoticeActive/acp-status/启动日志路径经 issue5079/wm-fastpath 套件钉住全绿;web-i18n 目录↔引用双向对账绿。
  6. 是否破坏缓存:不涉及(无缓存/重试/游标语义;loader 的 memo 只是进程内防重复读盘,按 name:size:mtime 签名失效)。
  7. 是否改了设计方向:否——严格按已批准设计 v2 §四/§七 实施;B>C>A 合并次序为设计规定。
  8. 是否引入了新的配置:新增用户目录 ~/.config/billion-context/announcements/(owner 已批准的设计点 2,P4 补文档);新增状态文件 <stateDir>/install-id(机器生成,非用户配置);本阶段无新 env。

ci-check added 2 commits November 3, 2026 00:27
…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.
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-11-02_notices-local-json-p2 (32e6178)

Latest build — install this exact version

npm install -g billion-context@0.0.7917-pr.5561.f61d400

This exact version is immutable and reproducible. The rolling pr tag tracks the newest test build across all PRs.

Recent builds (commit → version)

commit version build
32e6178 billion-context@0.0.7917-pr.5561.f61d400 build
ed69860 billion-context@0.0.7911-pr.5561.9b9163f build

Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr5561.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei ranxianglei changed the title feat: local JSON announcements lane — validator, targeting gates, hash-dismiss (#5548 P2) [PR] feat: local JSON announcements lane — validator, targeting gates, hash-dismiss (#5548 P2) Nov 2, 2026
…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.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

PR #5561(#5548 P2)审核结论:可合并 —— 前提是先合 P1 #5557。 方向对、实现干净、测试有牙、无回归;我顺手修掉一个 CI 红灯(unused-exports)并已推到分支。

我做了什么

  • 独立通读本 PR 全部 7 个文件的 diff(install-id.ts / local-announcements.ts / notices.ts / pck-notice.ts / admin.ts / 两个测试),核对 dismissal 往返一致性、内置公告是否被 targeting 误伤、registry helper 语义。
  • 本地跑通定向套件:notices-local-lane(22) + notices-registry + issue5079-pck-default-off + wm-fastpath-intro-notice + web-i18n = 52/52 绿;tsc --noEmit 干净。(全量回归以 CI 为准,未本地跑。)
  • 修了一个 CI 红并 push:unused-exports gate 在 head 上是红的——本 PR 导出了 8 个只在本模块内用到的声明(notices.ts 的 NoticeTone/NoticeDismiss/NoticeText/BuiltInContext/BuiltinNotice/VisibleNoticesOptions;local-announcements.ts 的 ANNOUNCEMENTS_DIRNAME/LocalAnnouncementLoad)。按 gate 自身处方去掉 export(保持模块内部),无行为变化。你在这个提交里已经把 KIND_PRIORITY 去导出、并把 registry 测试改用 NOTICE_KINDS 了——这 8 个是漏网的同类,我的修复与你的既有意图一致。修后 unused-exports 干净、typecheck 干净、52/52 复跑绿。commit 32e617897 已 fast-forward 推到 2026-11-02_notices-local-json-p2(仅 1 个提交,CI 会在新 head 重跑)。

结构化八问

  1. 是什么问题:公告面三期之二——让用户在本地放 JSON 文件自定义公告,与内置公告走同一套校验/过滤/分层合并/渲染。
  2. 什么原因导致的:设计缺口(Unified Announcement Panel Design (Approved): Built-in declarations + local JSON + remote GitHub raw — a single renderer | 公告面统一设计(已批准):内置声明 + 本地 JSON + 远程 GitHub raw,三来源一套渲染器 #5548)——此前只有代码内置提示,用户侧无自助渠道;本 PR 补本地车道 + 全套 targeting/校验/hash-dismiss 机制。属新增能力,非缺陷修复。
  3. 影响范围与严重程度:新增能力,默认零影响(目录不存在 = 零记录);两条内置横幅行为逐字节不变(都不带 versions/percent/since/until/priority/dismiss 字段,不受 targeting 门影响;P1 套件复跑绿)。严重度:不涉及。
  4. 怎么修复的:纯函数层(校验器/版本匹配器/分桶/时间窗/hash-dismiss/分层合并)集中在 notices.ts;fs 只存在于两个薄模块(install-id、local-announcements);服务端 collectVisibleNotices 一处汇聚三来源,B>C>A 先者优先。
  5. 是否有回归问题:逐项过——① dismiss 存储文件格式不变,键升级为超集兼容(旧裸 id 仍生效,升级不会复活已关横幅)✓;② 存储从排序无上限改插入序 + 200 FIFO 上限(正常用量远触不到)✓;③ pck/acp-status/启动日志路径经 issue5079/wm-fastpath 套件钉住绿 ✓;④ web-i18n 目录↔引用双向对账绿 ✓。不涉及 wire、不涉及两种压缩模式(纯公告子系统,不碰请求管道/消息重建/工具注入/nudge);不动 kernel(kernel-guard 绿)。
  6. 是否破坏缓存:不涉及(无缓存/重试/游标语义;loader 的 memo 只是进程内按 name:size:mtime 防重复读盘)。
  7. 是否改了设计方向:否——严格按 Unified Announcement Panel Design (Approved): Built-in declarations + local JSON + remote GitHub raw — a single renderer | 公告面统一设计(已批准):内置声明 + 本地 JSON + 远程 GitHub raw,三来源一套渲染器 #5548 已批准设计 v2 §四/§七 实施。
  8. 是否引入了新的配置:① 新用户目录 ~/.config/billion-context/announcements/(你已批准的设计点 2,P4 补 CONFIGURATION.md 文档);② 新状态文件 <stateDir>/install-id(机器生成随机 uuid,非用户配置,用于确定性百分比分桶);③ 本阶段无新 env。config-surface-guard 检查绿。

非阻塞观察(供你判断,均不卡合并)

  • env 感知目录解析器有 3 份近似重复:pck-notice.stateDirFor(P2 前已有)+ install-id.stateDirFor(本次新增的同款)+ local-announcements.announcementsDirFor(新 config 变体)。按「≥3 抽公共」可下沉到 paths.ts 一个共享 helper;因涉及 P2 前既有代码且这是叠加分支,我没擅自改,建议折进 P2 或留到 P3。
  • registerDynamicNoticeIds 的时序边:动态 id 在读路径(collectVisibleNotices)里注册;若某进程第一个请求直接是 dismiss POST(没先读 /notices 或 overview),knownNoticeIds 还没含该本地 id → 会 400。实际 UI 总是先读再 dismiss,所以不触发;要更稳可在 loadLocalAnnouncements/findNoticeRecord 时就注册(幂等 Set.add,1-2 行)。
  • isIso8601 偏松(基于 Date.parse,会接受非严格 ISO 如 "5/5/2020"):targeting 层还复检有限性,最坏只是校验比文档写的 ISO8601 略宽,不会崩。收紧与否是取舍(收紧可能拒掉用户现有能用的写法),留给你定。

判定

P2 本身质量达标、无阻塞缺陷;CI 的 unused-exports 我已修掉推上去。待办只剩一件:先合 P1 #5557,再把本 PR rebase 到合入后的 P1 之上即可合并(本 PR 叠在尚未合入的 P1 上)。其余观察项均为可选优化,不卡合并。

@ranxianglei

Copy link
Copy Markdown
Owner Author

(ai: vllm-qwen/qwen3.8-27b)

关系备注(重复判定):PR #5570(branch 2026-11-03_notice-p2,Nov 3 01:37)是同一 #5548 P2 范围(本地 JSON 公告)的第二份并行实现,叠在它自己的 P1 #5554 之上。同源同机制、不同实现;按先来后到,本 PR(Nov 2 17:11)先到应保留,#5570 已打 duplicate 标签、待 owner 关闭。

独立审核在 #5570 head 确认了 4 处已验证缺陷(persistent-dismiss 端点缺口 + caret 测试期望与标准 semver 矛盾 + TS2345×2 + unused-exports×5),明细见 #5570 的审核评论。本 PR 对应实现(服务端按 id 找回记录后推导 dismiss 哈希键)不受影响。系列取舍(X 系 vs Y 系)已在 #5570 线程提交决策请求。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

收到。我把 git 图拉出来核了一遍——重复是「系列级」的,不止一个 P2。先给结论:同意保留本 PR(#5561,先到),#5570 维持 duplicate(我不关,关单归你)。但真正要拍板的是「留哪条系列线」,这点已在 #5570 线程立了决策请求,我不越线替代它。

git 证据(我实测)

两条系列都从同一个 v0.1.212 提交 daa082ead 分叉,彼此零共享非-master 祖先:

两系各自独立实现了同一套「统一公告注册表」(src/notices.ts + admin.ts + web client/i18n/page),还各自撞了同一个 unused-exports 门并各自修了(A:1dda83eb6;B:ae3e936a6)——同机制并行开发,坐实是重复而非互补。

给决策补一个事实

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 当前是从 A-P1 @ 31668771b 切出的,不含 A-P1 后来加的 1dda83eb6(又一次 notices.ts 导出面清理,动了 7 个声明)。等 P1(#5557) 合入后把本 PR rebase 到含它的 master 时,请重跑 unused-exports + tsc——确认我推的 32e617897(去导出 8 个声明)与 1dda83eb6(7 个)能干净合成(大概率不相交,但要验)。我没现在强行 rebase/force-push:P1 还没合,对着临时 P1 head rebase 只会多一轮无谓改动。

状态(八问速览)

  1. 是什么问题:Unified Announcement Panel Design (Approved): Built-in declarations + local JSON + remote GitHub raw — a single renderer | 公告面统一设计(已批准):内置声明 + 本地 JSON + 远程 GitHub raw,三来源一套渲染器 #5548 P2 出现两份并行实现(A/B 两系),需定夺留哪条线。
  2. 什么原因导致的:两个会话对同一批准设计各自落地、未先查重对齐系列线。
  3. 影响范围与严重程度:不影响已发布行为(两系都还没进 master);风险在合并时选错线、或两边半合并导致 notices.ts/admin.ts/web 冲突。流程性问题,非线上缺陷。
  4. 怎么处置的:git 取证确认系列级重复;本 PR 侧我只做了自己的 unused-exports 修复(32e617897),未触碰 [PR] feat(web): local announcements — drop a JSON next to config, get a banner (#5548 P2) #5570。
  5. 是否有回归问题:不涉及线上回归(未合入);唯一技术点是 rebase 时的导出面合成(见上提醒)。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:否——两系是同一已批准设计 v2 的实现分歧,不是方向分歧。
  8. 是否引入了新的配置:不涉及本条(配置面在 P2 正文已列:announcements/ 目录 + install-id 状态文件,P4 补文档)。

判定:本 PR(#5561)质量与可合并性不变——待 P1(#5557) 合入后 rebase 即可合并;系列取舍等 #5570 线程的决策。我这边不关任何单、不碰 #5570。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

🔶 需要决策
(ai: vllm-qwen/qwen3.8-27b)

结论先行:本 PR 与 master 的冲突不是机械冲突,而是「公告子系统两套不兼容实现」的设计分叉,无法用「取并集」式 rebase 安全解决。任何自动 force-push 都会二选一踩雷——要么覆盖已上线的简单注册表并回退 11-09 上线的 iot-thinking 提示,要么产出不编译的混合体。故停手,请你拍板方向。

我查证到的事实(全部本地 git 实测,非猜测)

  1. 本 PR 叠在 A 系 P1(31668771b,完整三来源机制:NoticeRecord 带 versions/percent/since/until/priority/dismiss/多语言 + registerDynamicNoticeIds + mergeNoticeLayers)之上;P2(本 PR 主体)在其上加本地 JSON 车道。
  2. src/notices.ts 在分叉点 daa082ead8(v0.1.212) 上不存在——master 与本 PR 是「双方各自新增同一文件」(add/add),不是改同一份已有代码。
  3. master 已上线另一套实现:经 PR [PR] Unified Announcement Panel: Built-in Registry + Local JSON Files + Remote Dynamic Sources (Done in One Pass) | 统一公告面:内置注册表 + 本地 JSON 文件 + 远程动态源(一次做完) #5575(2026-11-03_unified-notices-surface, 11-03 合入) 落地的「简单注册表」——NOTICES 表(id/tone/keys/active) + visibleNotices(),仅收敛既有两条横幅;随后 [PR] 2026 11 09 iot incompat notice upstream #6015(11-09) 又在其上追加了 dsh iot-thinking 告警条目。这套设计里没有 P2 依赖的任何 targeting 机制。
  4. P2 硬依赖 A 系 API:它从 ./notices.js import 了 validateNoticeRecord / BUILTIN_NOTICES / dismissKeyOf / dismissModeOf / mergeNoticeLayers / noticeVisible / passesTargeting / registerDynamicNoticeIds / sortNotices / visibleBuiltInNotices / TargetingContext——这些符号在 master 的 notices.ts(我通读了全部 109 行,仅导出 NOTICES/probeDshIotThinking/dshIotThinkingActive/visibleNotices)里一个都不存在。所以无论怎么 rebase,typecheck 都过不了,除非整体换掉 master 的实现或重写 P2。pck-notice.ts / admin.ts 两边也都有改动,会叠加内容冲突。
  5. floor 8 提出、当时悬在 [PR] feat(web): local announcements — drop a JSON next to config, get a banner (#5548 P2) #5570 的「留哪条系列线」决策,实际上已被「master 合入了哪条」回答了——简单注册表那条线已上线且继续在其上迭代;本 PR 的 A 系地基从未进入 master。

三个选项(逐选项影响/风险见下方八问第 3、5 问)

  • A. 采用 A 系完整机制,替换 master 现有注册表:把 A 系 notices.ts 全套搬上来覆盖 master 版本,并把 11-09 新加的 iot-thinking 条目重新吸收进新 schema。
  • B. 保留 master 已上线的简单注册表为基座,把 P2 的本地 JSON 能力重做到它上面(推荐)。
  • C. 判定本 PR 已被 master 现状取代:保持不动、待你决定放弃或另起炉灶;P2 的本地车道价值在需要时基于当前 master 重新立项。

结构化八问(决策请求)

  1. 是什么问题:Unified Announcement Panel Design (Approved): Built-in declarations + local JSON + remote GitHub raw — a single renderer | 公告面统一设计(已批准):内置声明 + 本地 JSON + 远程 GitHub raw,三来源一套渲染器 #5548 公告面存在两条并行实现线(A=完整三来源机制 / B=简单注册表),后者已随 [PR] Unified Announcement Panel: Built-in Registry + Local JSON Files + Remote Dynamic Sources (Done in One Pass) | 统一公告面:内置注册表 + 本地 JSON 文件 + 远程动态源(一次做完) #5575 上线并在其上加了 iot-thinking;本 PR(A 系 P2) 叠在未上线的 A 系地基上,与 master 形成「同一文件两套不兼容定义」的冲突,无法机械 rebase。
  2. 什么原因导致的:同一批准设计的两条并行落地(floor 8 已记录),其中一条([PR] Unified Announcement Panel: Built-in Registry + Local JSON Files + Remote Dynamic Sources (Done in One Pass) | 统一公告面:内置注册表 + 本地 JSON 文件 + 远程动态源(一次做完) #5575)先被合入 master 并持续迭代,使 A 系地基从未进入 master——冲突本质是「架构选型已被 master 的事实改变」。
  3. 影响范围与严重程度(逐选项):
    • A:波及整个公告子系统(notices.ts / admin.ts / pck-notice.ts / web client·i18n·page 全量改写),且必须回退并重吸收已上线的 iot-thinking 提示;严重度=高(改动面大、回退线上功能)。
    • B:只新增本地车道能力,master 现有三条横幅行为逐字节不变;严重度=中(属新功能开发而非缺陷修复)。
    • C:不影响线上;本 PR 维持 dirty 不可合并;严重度=低(仅流程/排期)。
  4. 怎么修复(推荐选项 B 的思路):以当前 master 的 notices.ts(简单注册表) 为基座,把 P2 的可复用纯函数(校验器、版本匹配器、百分比分桶、时间窗、hash-dismiss 键推导)适配到 NoticeEntry 体系,本地文件加载器(install-id / local-announcements)作为独立车道挂进可见性合并点;内置三条横幅逐字节不动。这是一次基于当前 master 的新 PR,不是对现分支的 rebase。
  5. 是否有回归风险(逐选项):
    • A:有实质回归风险——覆盖 master 的 notices.ts 会丢掉 11-09 上线的 iot-thinking 告警(除非完整重吸收,否则该提示直接消失);且推翻已上线的架构方向。
    • B:无对现有行为的回归(内置横幅不变,本地车道默认零记录);风险集中在「重做是否完整还原 P2 语义」(targeting / hash-dismiss 等),可用测试钉住。
    • C:无回归(不改代码);代价是本 PR 长期挂起。
  6. 是否破坏缓存:三个选项均不涉及请求管道 / 压缩 / 缓存语义(纯公告展示子系统)。
  7. 是否改了设计方向:A=是(推翻已上线方向,回到完整三来源 v2);B=否(沿用已上线方向,补本地车道);C=暂不定。
  8. 是否引入新配置:A/B 都会带来本地公告目录 ~/.config/billion-context/announcements/ + <stateDir>/install-id(P2 原设计点,文档 P4 补);C 无。

选项对比表

A 采用 A 系 B 重做 P2 到简单基座(推荐) C 判定取代/挂起
保住已上线 iot-thinking 需重吸收(有风险) ✅ 天然保留 ✅ 保留
交付 P2 本地车道价值 ✅ ✅ ❌(另起炉灶)
改动面 大(全子系统) 中(新 PR) 无
回归风险 高 低 无
与已上线方向一致 ❌ 推翻 ✅ 一致 ✅ 一致
工作量 高 中 低

推荐:B。 若超时未决的安全默认:保持本 PR 原样不动(不 force-push 任何猜测性解法),冲突维持 dirty;由你在 B(推荐)/C 间定向后我再执行——因为自动动作在此处必然踩到「回退线上 iot-thinking」或「推出不编译分支」二者之一,宁可停手。

(本次我未动分支、未 push、未改 PR 正文;已按规则打上 needs-decision 标签。)

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

1 similar comment
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

🔶 需要决策
(ai: vllm-qwen/qwen3.8-27b)

第 2 次触发 · live 复核:状态无变化,仍等你拍板。 本轮按 status-freshness 重新拉了 live git(非凭记忆),结论与昨天 floor 12 完全一致——仍是「同一文件两套不兼容公告实现」的设计分叉,未收到你的 A/B/C 定向。

本轮复核到的 live 事实(本地 git 实测):

所以: 任何自动 rebase 都只能二选一踩雷——要么覆盖已上线注册表并回退 11-09 上线的 iot-thinking 提示,要么产出不编译的混合体。完整选项 / 八问 / 对比表见 floor 12,此处不重复贴。

仍需你拍板(回一个字母即可):

  • A = 采用 A 系完整机制替换 master 现有注册表(须重吸收 iot-thinking);
  • B = 保留 master 已上线的简单注册表为基座、把 P2 的本地 JSON 车道重做到上面(我推荐);
  • C = 判定本 PR 已被 master 现状取代而挂起。

超时安全默认:保持本 PR 原样不动——我不推任何猜测性解法,等你定向后再执行。

(needs-decision 标签已在位;本轮未 push、未改分支、未动 PR 正文。)

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[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 原样不动。你定向后我立即执行。

结构化八问(本次运行)

  1. 是什么问题:公告子系统存在两套不兼容实现(A=完整三来源机制 / B=简单注册表),后者已随 [PR] Unified Announcement Panel: Built-in Registry + Local JSON Files + Remote Dynamic Sources (Done in One Pass) | 统一公告面:内置注册表 + 本地 JSON 文件 + 远程动态源(一次做完) #5575 上线;本 PR(A 系 P2) 与 master 在 src/notices.ts 上构成「同文件两套定义」冲突。
  2. 什么原因导致的:同一批准设计的两条并行落地,其中一条([PR] Unified Announcement Panel: Built-in Registry + Local JSON Files + Remote Dynamic Sources (Done in One Pass) | 统一公告面:内置注册表 + 本地 JSON 文件 + 远程动态源(一次做完) #5575)先合入并持续迭代,A 系地基始终未进 master——冲突本质是架构选型已被 master 事实改变。
  3. 影响范围与严重程度:不影响线上行为(本分支未合入);阻塞点在合并选型,非线上缺陷。严重度:流程性/排期。
  4. 怎么修复的:本轮未改代码(无机械解法可安全执行);仅 live 复核状态 + 再次升级等待拍板 + 补打标签。
  5. 是否有回归问题:不涉及(未动任何分支/文件)。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:本轮未改;方向取舍仍待你在 A/B/C 间拍板。
  8. 是否引入新配置:本轮未引入(B/A 选项的配置面已在 floor 12 列出)。

判定:维持挂起,等你 A/B/C 定向。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[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 src/notices.ts, not a mechanical one — any automatic force-push either regresses the shipped iot-thinking notice or ships a non-compiling hybrid. Full options A/B/C + 八问 + comparison table are at floor 12 (re-stated at floors 20 & 22); not re-posting them here to avoid clutter.

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。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

1 similar comment
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[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 c26c31a, was 33104b1f) — web handoff rendering (#6260), blockOps gate (#5765), snapshot write lifecycle (#6186/#6166), anthropic trailing-systems (#5441), etc. None of them touch the actual blocker:

So this remains a design fork, not a mechanical conflict: any rebase either overwrites master's shipped notices.ts (regressing the iot-thinking notice #6015) or leaves the tree non-compiling. I have not pushed, rebased, edited the PR body, or opened anything new.

Still awaiting your pick (full options + comparison table at floor 12, restated at 20 & 22):

  • A — adopt the A-series machinery, replace master's registry (must re-absorb [PR] 2026 11 09 iot incompat notice upstream #6015).
  • B — keep master's shipped simple registry as the base, rework P2's pure functions onto its schema ← recommended.
  • C — treat this PR as superseded; hold/drop it.

Safe default if undecided: leave the PR untouched (no speculative force-push).


中文八问(结论未变,完整选项表见 floor 12):

  1. 是什么问题:PR [PR] feat: local JSON announcements lane — validator, targeting gates, hash-dismiss (#5548 P2) #5561 与 master 的 src/notices.ts 是设计分叉,不是机械冲突。
  2. 什么原因导致:fork 点该文件尚不存在;master 经 [PR] Unified Announcement Panel: Built-in Registry + Local JSON Files + Remote Dynamic Sources (Done in One Pass) | 统一公告面:内置注册表 + 本地 JSON 文件 + 远程动态源(一次做完) #5575 落地了另一套简单注册表,而 P2 依赖的 A 系列机制([PR] feat: unified announcement surface — built-in registry + single renderer (lane A, #5548 P1) #5557)至今未合入。
  3. 影响范围与严重程度:仅本 PR 无法合并、持续 dirty;不影响线上运行。
  4. 怎么修复:未修——需先拍板 A/B/C(推荐 B:以 master 简单注册表为基座,把 P2 纯函数重做上去)。
  5. 是否有回归问题:强行 rebase 会覆盖 master 已上线的 iot-thinking 通知([PR] 2026 11 09 iot incompat notice upstream #6015)= 严重回归,或产出不可编译的混合体——故未动。
  6. 是否破坏缓存:不涉及。
  7. 是否改了设计方向:这本身就是设计方向抉择,等你定。
  8. 是否引入新配置:P2 会引入本地 JSON 公告面;B 方案下并入现有注册表,具体配置项待拍板后另议。

判定:维持 needs-decision,等待你的 A/B/C;本轮未对分支做任何改动。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[ework] CI fix verified green ✓

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant