Repository navigation
feat: conditionally protect acp_rule pairs by stream-derived rule liveness - #378
ranxianglei wants to merge 2 commits into
Conversation
…eness acp_rule moves out of ALWAYS_PROTECTED_TOOLS into collectRulePairProtection: a record pair stays protected iff its id survives an ordered walk of acp_rule tool-results (Recorded adds, Removed deletes, Cleared clears). All other acp_rule exchanges become ordinary foldable content. Fail-closed for malformed 'Recorded ' results. No-op safe without removal/clear events; zero byte change until a natural fold (billion-context#1177, owner-approved semantic change).
📦 Built Package ArtifactBranch: Option A — Install from npm PR tag (recommended)In your adapter project: npm install acp-kernel@pr-378Each push to this PR publishes a new version under the Option B — Download artifact
tar xzf acp-kernel-pr378.tgz
npm install ./packageThis comment is automatically updated on each push. |
[bot] 🏷 Review: mergeable — direction sound, no regressions found, diff clean. I pushed one test-only commit while reviewing (below). Merge is yours: #378 ① Original issue (#377) — direction checkVerified the claimed root cause: pre-change, ② Regression inventory (existing behaviors touched)
③ CodeTwo-pass walk (liveness, then live-record collection) is O(n) over results; pairing via the call-side
④ TestsThe 11 shipped tests have teeth: exact protected-range assertions (m00002–m00003, everything else compressible incl. the dead pair and delete trace), no tautologies. Gap I closed directly: the CCR skip-store guard and the ⑤ Diff cleanlinessSingle concern across 11 files (+390/−21 before my test commit), no unrelated churn; doc comments updated where the codebase actually made claims (types.ts, rules.ts, protected.ts). DESIGN.md et al. make no acp_rule-protection claims, so no doc drift. Post-merge sequencing (§7.4)This modifies a §7.3 contract (protected-tool filtering), so it ships by the manual cross-repo path: release acp-kernel first, verify CI was green on 一句话中文摘要:审核通过——流派生规则活性保护方向正确、五处消费点接线一致、缓存安全且无回归;我直接补了 CCR 跳过存储与 absorb 拒绝两个缺失的守护测试(commit 2f1e50a,全套 1042/1042 过),可以合并。 |
|
暂时搁置(维护者决定)。 理由:按消息流文本协议(Recorded/Removed/Cleared)推导存活状态是补丁式做法——rule 的增删改查需要一套综合设计先行:
先出设计(issue 或 RFC),再回来重做本 PR。 |
[bot] 🏷 收到,已按维护者决定执行搁置:
重做时的起点建议:以 #390 的方案拍板为准,PR #378 中可复用的部分主要是五处消费点的接线骨架与测试结构,liveness walk 本体预计整体替换。 一句话中文摘要:已按决定搁置——立了 RFC #390(建议宿主声明 typed state 为主、内核乐观镜像为辅),PR 代码保留为重做参考,draft 切换受环境 API 限制需人工操作。 |
Fixes #377
What changed
acp_rulemoves out ofALWAYS_PROTECTED_TOOLSinto a new conditional protection, derived from the visible message stream itself:collectRulePairProtection(messages)walks acp_rule tool-results in order. Result text forms a closed partition with host executors (billion-contextexecuteRuleis the reference implementation):Recorded ruleN: …adds the id to a live set,Removed ruleN: …removes it,Cleared N rule(s).clears it.toolCallId; results without a projectedtoolNamepair via the call-side name) is protected iff its id survives the walk. Kernel contract: ids are never re-issued, so final-set membership equals per-event liveness.Recordedwith an unparseable id keeps its pair protected (format drift must never silently fold a live rule).Wired at all five protection consumers:
buildCompressibleRanges(fold gate),assignRefsNode(BLOCKED refs, outside the config gate like media),filterProtectedToolMessages, CCRstoreLargeResultsskip-store check, and absorb (isAbsorbCandidate+applyAbsorbrefusal). Exported from index for hosts/tests.Why stream-derived and not a state.rules lookup
In plugin mode the agent owns compression: folding runs in the agent's own kernel copy whose state has no rules table (rule records are written server-side by the host executor). A state lookup would misjudge live rules as foldable there. The message stream is identical in both modes, so the derivation is mode-agnostic with zero cross-process sync.
Behavior-change disclosure (owner-approved)
Removed/Clearedevents in the history, every record pair stays protected — behaviorally identical to today. This release alone changes nothing until hosts actually delete rules (billion-context deletes ship in feat: acp_rule delete/clear — wire kernel removeRule/clearRules (#1177) billion-context#1178 / issue #1177).acp_retrieve.compressstays unconditionally protected (it carries block refs). This was explicitly approved by the owner in the #1177 thread: 「内核你可以搞,只要是不破坏缓存就可以搞」.Tests
New
tests/rule-pair-protection.test.ts(11 tests): unit coverage of liveness walk (live / removed / cleared / re-record-after-remove / malformed fail-closed / listings+errors inert / toolName pairing variants / empty), plus integration throughbuildCompressibleRangesproving the gate (dead pair compressible, live pair excluded) and no-op safety (record-only history fully protected). Updated the one stale assertion intests/rules.test.ts.Pre-flight on rebased head (master 312eb11): typecheck clean · full suite 1040/1040 pass · build clean.