Repository navigation
feat: dsh persona fingerprint — session id + system hash split for id-sharing hosts (#1916/#1307/#1314) - #1956
Conversation
📦 Built Package ArtifactBranch: Option A — Install this exact build (recommended)npm install -g billion-context@0.0.1963-pr.1956.f0bc272This exact version is immutable and reproducible. The rolling Option B — Download artifact
tar xzf billion-context-pr1956.tgz
npm install -g packageInstall instructions are refreshed on each push. |
[bot] 🏷 收到,开始 review PR #1956(dsh persona fingerprint)。已定位分支 |
[bot] 🏷 Review 完成 — 结论先行:可合(merge-ready)。方向审、回归审、代码审、测试有效性、diff 整洁度全过;唯一待你拍板的是第二 commit 的 结构化七问1. 是什么问题:dsh 给一个会话的每条模型请求盖同一个 2. 什么原因导致的:根因在 session key 推导层——key 只取客户端 conversation id,id-sharing 宿主让辅助人格与主 turn 不可区分。#1307 的 guard 修在被污染的消费端(rememberPluginMessages),是堵不是疏;本 PR 修在产生端(keying),方向正确。 3. 怎么修复的:对 allowlist 宿主(dsh,证据准入同 #1104/#1107 纪律)复用内核既有 4. 是否有回归问题:无。逐项过触碰路径的既有行为:
5. 是否破坏缓存:否。upstream prefix cache 依赖转发的客户端自带 identity 值, 6. 是否改了设计方向:无转向——把既有 7. 是否引入了新的配置:是—— 验证证据
两点非阻塞观察(均不要求改)
判定可合。 建议顺序:你签核 |
…-sharing hosts dsh stamps ONE x-bili-plugin-conversation id on every model request of a session, INCLUDING the auto-review classifyRisk() calls (fixed REVIEW_POLICY system + a freshly-flattened user blob, fired before every tool call under the Auto permission tier). Those review requests walked the full pipeline under the MAIN conversation id: they overwrote the usage baseline (#1916), evicted remembered snapshots (#1307's guard was a partial stopgap), and fed orphan-GC — while the review blob is synthesized fresh every time, so compressing it has zero reuse value. Key dsh traffic by id + system hash (kernel subagentNamespace anchor semantics): the FIRST system seen under the id keeps the raw key (the main turn claims it — dsh composes its main system once per session and puts the volatile time-context in a USER message, so main turns never fork mid-conversation), a different system forks onto <id>|sub:<fp> (the review persona), and an empty system is non-anchoring (verbatim key, system-less auxiliary calls keep riding the main session). - src/session-id.ts: dshPersonaFingerprintApplies (evidence-permitlist, the #1104/#1107 discipline — do NOT enable wholesale, #1106) + openaiSystemTextForPersona. - src/server.ts: fork applied on the openai and anthropic lanes; personaForked sessions record under their suffixed id (recordPluginSession) so the single-valued conversations map keeps the raw key owned by the main session (#970 discipline). - AGENTS.md: Key Design Decisions #9 — the rule for future hosts that reuse one session id across personas. - tests: fork/stability/allowlist/anthropic-lane coverage (peekSession — getSession is get-or-create and would mint the sessions we assert about). Refs #1916 #1307 #1314
…l 8787 proxy Found while validating the persona-fingerprint branch: the idle test expects NO healthy proxy among discoverHealthyProxyOrigin's candidates, but a developer running a manual proxy on the default 8787 (the exact machine this suite runs on) makes the entry serve the REAL tools — a correct production behavior (idle fallback prefers a live proxy) that flipped the test red. BILI_MCP_DEFAULT_ORIGIN (new env, mirrors the BILI_MCP_PROXY pin family; default unchanged) lets the test pin the last-resort candidate to a dead port. Disclosed under config surface in the PR body.
d95e8ce to
e121512
Compare
问题
dsh 给一个会话的每一条模型请求盖同一个
x-bili-plugin-conversationid——包括 auto-reviewclassifyRisk()(Auto 权限档在每次工具调用前发一条:固定 REVIEW_POLICY system + 新拼的单条 user blob)。这些 review 请求一直以主会话身份走完整管线:lastInputTokens基线(并发同 session-id 流互相覆盖 lastInputTokens 基线:#388 侧请求分类漏掉「整段上下文单消息」形态,#1595 re-anchor 放大覆盖 #1916);remembered快照,长会话里 plugin 路径的compress全败(Requested range(s) cannot be anchored) #1307 的 ≤2 条形状护栏只是部分止血);修法:persona 指纹(id + system 哈希,"hash 不一样自动分裂")
复用内核既有的
subagentNamespace锚点语义(openai/anthropic 两条线):<id>|sub:<fp>,review 人格进自己的会话(基线/快照/压缩状态全部隔离),后续 review 复用同一个 fork(稳定,不是每条一 fork);recordPluginSession(Subagent first token stalls 1-2min: withSessionLock covers full forward + slow flash upstream first byte #970 纪律),raw key 永远归主会话——/acp 查询、MCP tool 路由不被 review 抢走。为什么对 dsh 安全(已实证)
session.v3.jsonl.zstd的system/message事件)每会话只记一次;易变的 time-context 走 user message 不进 system(dsh-time-context 源码核对);为什么是 allowlist 而不是全量
dshPersonaFingerprintApplies(src/session-id.ts)只认x-bili-plugin: dsh。这是 #1104/#1107 的证据准入纪律:对其他宿主,system 中途漂移=同一会话演化(升级/插件/AGENTS.md),全量启用会把压缩状态无意义地清零(#1106)。未来发现复用 session id 的宿主,先补流量证据再加进这个谓词——已写入 AGENTS.md §2 Key Design Decisions #9。变更
src/session-id.ts:dshPersonaFingerprintApplies+openaiSystemTextForPersona(拼全部 system 消息文本)。src/server.ts:openai/anthropic 两线的 conversation 推导加 fork;personaForked传给recordPluginSession。AGENTS.md:Key Design Decisions 新增 release v0.1.2 #9(机制 + 未来同类宿主处理纪律)。tests/dsh-persona-fingerprint.test.ts:fork/稳定性/allowlist 钉死/anthropic 线/无 system 非锚定(存在性断言用peekSession——getSession是 get-or-create,会自己造出被断言的会话)。第二个 commit:测试隔离(与本特性无关,验证时撞见)
本机有一个开发者手动的 bili 长驻默认端口 8787(完全正确的生产行为:degraded 空闲 fallback 优先找活代理)→
zcode-mcp-degraded的 idle 用例翻红。新 envBILI_MCP_DEFAULT_ORIGIN(镜像BILI_MCP_PROXYpin 家族,默认值不变)让测试把末位候选钉到死端口。config surface 披露:新增 env
BILI_MCP_DEFAULT_ORIGIN(仅 mcp-entry 的 degraded 发现链最后一位候选;默认 8787 不变;无 config.json 字段;不与任何现有机制重叠——BILI_MCP_PROXY是显式 pin,此变量是默认兜底覆盖)。若 owner 认为不该加,回退方案=用例在 8787 有活代理时 skip(本地永久损失覆盖);一行即可 revert,随时可撤。验证
Refs #1916 #1307 #1314