Repository navigation
[REQ-131][CODE] #1129 reopen:策略文档轴抵达目录与执行咽喉 + dynamic tool policy inventory - #1147
Merged
Merged
Conversation
jinjunnn
added a commit
that referenced
this pull request
Aug 26, 2026
…/14 · 负向控制 8/8) (#1150) 上一轮 #1144 的取证跑在 c3c5830;#1147(ac#1129)在那之后合进 alpha,换掉了 session/tools.ts 里执行咽喉那一格(permission.ask → AlphaToolPolicyGate.gateToolExecution), 于是「这条链是否仍到得了 bash 工具」变成零证据。本轮只补这一格。 被测 sha 8a43800(= 构建时的 origin/alpha,含 #1147/#1148),四份结果 JSON 自报一致。 构建走仓内离线快照(MODELS_DEV_API_JSON,退出码单独取、built in 行数核为 3), 避开上一轮那次「build 退出 1 而 package:mac 照跑上一份 out/」的假成功。 - 围栏臂 ×2 轮:shell 工具 14/14 不落盘、prompt !command 14/14 不落盘,正样本落盘; - 反向臂 ×2 轮(只改打包副本里 wrapper 那一行,ext sha 9cc40e89… 与前两轮逐字相同): 两个驱动面各 14/14 落盘; - 四轮各 21 pass / 0 fail;56 个 escape 格全部 processStarted=true, 28 次工具调用 tool=bash / completed / commandIntact / 按 callID 认领; - 负向控制 8/8:只加一个配置键 builtin::bash=deny,引擎下发的工具从 16 个降到 15 个 (少的正是 bash)、什么都没落盘;allow 臂在同一脚本同一产物上跑通 —— 证明「链是通的」 是真实测量而非空转。README §4 同时写清它**不能**区分新旧闸,那由产物出处回答; - 产物出处:五个在 c3c5830 零命中、在 8a43800 命中的标记全部出现在 app.asar 里 (grep -a;该文件有 2,689,313 个字面 NUL),并附手段自证的正/负样本。 未闭合项不变:AC1 字面的「真模型回合」仍缺模型凭据;本轮不跑 hardened 臂(AC2 结论仍以 上一轮为准,围栏与签名配方本区间未动)。 未改任何生产代码。取证 runner 沿用上一轮那一份,只修了它的 finally 里 spawnSync("git",…).stdout.trim() 在 cwd 消失时抛错、导致整轮结果写不出来的缺陷 (改成 ?.trim() ?? "";该值只进结果对象的 gitSha 字段,不参与任何 probe 判定)。 Refs #1144 Claude-Session: https://claude.ai/code/session_01QHDS2BFKuzm9uNH1svU2oj Co-authored-by: jinjunnn <slmbaovanetti99@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
jinjunnn
added a commit
that referenced
this pull request
Aug 28, 2026
* chore(release): 0.1.3 -> 0.1.4 v0.1.3 已于 2026-08-18 发布,而其后合入 81 个 commit(含 #1147 策略咽喉、#1149 沙箱 set-ID 等真实产品改动)。用同一版本号重打会让 updater(按版本判断)不推更新,同时分发出与已发布 0.1.3 字节不同的产物 —— 故按 patch 位进位。 本次只做版本位。签名+公证包**未产出**:本机到 Apple 的时间戳/公证服务不可达 (timestamp/appleid/notarize.apple.com 均解析为 fake-IP 198.18.x.x,3 轮 ×3 端点 9/9 无响应; 正样本 api.github.com 403、openrouter.ai 200 证明测法有效),codesign --timestamp 直接失败。 未用 --timestamp=none 绕过 —— 那样签出的产物无法公证、Gatekeeper 拒,是假成功。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * release: ship alpha-code 0.1.4 Move the 10 Unreleased user-visible notes into 0.1.4, and pin the #640/#681 consumer cutover fixtures to the shipped ui-mac version — bumping package.json without them fails the consumer lock tests (verified: reverting one fixture to 0.1.3 turns alpha-contracts-consumer red, exit 1 / 1 fail). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FryTvmnuisnpExiwdY1JpL --------- Co-authored-by: jinjunnn <slmbaovanetti99@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
jinjunnn
added a commit
that referenced
this pull request
Sep 20, 2026
`sync-upstream` 最后一次成功是 2026-07-22T08:06:35Z(run 29902706228),此后 **59 次连续失败、零通知**(2026-07-23 → 2026-09-19,实测自 run 历史)。失败的唯一 输出是一条 Actions 日志,而 `sync-upstream-push.yml` 只消费 `conclusion == 'success'` —— 失败那一半的结论**没有任何读者**。这就是本票的全部内容。 连败不是一个原因:07-23→08-07 的 16 次死在 `bun install` (`@opencode-ai/client@file:../app/vendor/*.tgz failed to resolve`,即 `#1272` 修掉的 那个顺序缺陷);08-08→09-06 的 30 次是 `packages/desktop/src/main/index.ts` 冲突; 09-07 起的 13 次是 `packages/opencode/test/provider/transform.test.ts` 冲突。 后者在 north-star 收编白名单里(`#1147` 有意改的),所以那句 「the only-add discipline was broken」在这里是假的 —— 每一个被收编的上游文件都是一台 永久冲突发生器,而冲突落在那里**必须**由人解(自动解会静默丢掉一侧)。`ac#1248` 的 追平 2026-09-06 落地,09-07 那一轮就又红了。 本提交不碰那条 abort(它是对的),只补上缺的那半: - `.github/workflows/sync-upstream-alert.yml` —— `workflow_run` 的 failure 消费者, 与 `sync-upstream-push.yml` 同一个信任形状:持 `issues: write` 正因为它**不执行 合并树里的任何代码**(checkout alpha、不跑 bun install、只跑零依赖脚本)。 - `scripts/sync-upstream-alert.ts` —— 建/刷新一张带 `sync-upstream-failure` 标签的 追踪票。身份锚是正文里的 marker 而不是 label(只认 label 会把人手写的正文整段 PATCH 掉);形态不变只刷新正文不发评论;任何 API 失败与缺 token 一律非零退出。 - `packages/ui-mac/src/main/sync-upstream-alert.test.ts`(11 条,已登记精确条数)—— 起真 HTTP 桩冒充 GitHub API、跑生产脚本本体;接线那两条各带变异臂。 实证:`scripts/assert-frontend-patch-roundtrip.sh`(`#976` 那道会保住我们自有改动 不被 sync 静默删掉的门)今天在 alpha 上有效 —— 干净 HEAD rc=0(真比了 tree sha), 往 packages/app 写一行不重生补丁 rc=1 并点名该文件,重生后回 rc=0。 Refs #976 Co-authored-by: jinjunnn <slmbaovanetti99@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1129
Refs #723(REQ-131 父需求,不用关闭关键词)
方案基线:#724 CLOSE_DECIDE §3/§4/§5(末条)/§6 + §9 第 2 条。本 PR 补 reopen 点名的两件:dynamic inventory/API 与 策略文档轴抵达咽喉。上一轮(PR #1135)落地的 E1–E6 identity(ruleset)轴执行未重做、未回退——23 条 #725 探针断言一字未改,本轮全绿。
一、dynamic inventory/API(#724 §5 末条)
落点:引擎内
AlphaToolInventory.Service.list()(packages/opencode/src/permission/alpha-tool-inventory.ts),wire 形状(renderer 可原样 import)packages/schema/src/alpha-tool-inventory.ts,返回值经 schema decode 自证(形状漂移 loud fail)。从 live ToolRegistry / MCP.tools() / host 谓词派生,不读历史ToolPart.display、不读 UI 名单(§5 禁令);effective 判定与咽喉是同一个 resolver(同一resolveToolPolicy纯核 + 同一合成),差别只有 §6 允许的 snapshot vs 每次重读。字段清单 ↔ 设计稿 §3 表逐行覆盖
services[].class+services[].tools[](条数 = length)services[].source+services[].origintools[].identity.nameservices[].bindingDigest/tools[].bindingDigest(alpha-cloud = verified authority 证据,其余 = 宿主派生当前 binding,与 resolversubjectBindingDigest同取向)removeRecord(#1128 已有;record字段回显现有 override)tools[].effective.state/action/reason(9 型 wire 镜像;引擎侧 exhaustive-switch = 编译期漂移闸)reason.kind = "default"(class)/"user"(level)reason.kind = cap-managed / cap-managed-unreadable / cap-entitlement / cap-hard-denyreason.kind = "binding-changed"+ 当前 digestuser.status = quarantined+ reason(重置走既有reset())ToolPolicyWriteError(#1128 已有,非 inventory 职责)partition(与引擎inspect()一致)tools[].billing?(schema 在场;今天引擎里没有任何 billing fact 生产方⇒恒缺席⇒UI 如实显示「未知」——如实声明,不假装有供给)tools[].newlyDiscovered(动态类 && 零匹配记录)invalid.count+entries[].detail(owner Q1 裁决:计数入正文,原因归开发者详情)少给的行:无。
classRecords额外提供(四组总开关的用户 override 呈现)。二、策略文档轴抵达咽喉(#724 §3/§4/§6)
合成次序(照 §4,不自创),全部在共享 gate
packages/opencode/src/permission/alpha-tool-policy-gate.ts:Permission.evaluate判定后折进 cap(hardDeny:["permission-ruleset"])——deny 是上限,文档轴 enabled 与 session grant 都撬不开;它的 ask/allow 留在原地生效(既有闸保留)。AlphaToolPolicy.resolve([REQ-131][CODE] 解析并持久化分层工具策略 #1128):managed/entitlement cap → 用户 selector(tool>service>class,binding guard:enabled+digest,当前 digest 由调用方在调用时重新派生——mcp = 生效配置 entry 去秘密 digest(rebind 检测),plugin = 本装载代 digest,builtin/host = 应用常量)→ 四类默认(本地 enabled,其余 ask)。Permission.ask(不另造第二个审批引擎):deny ⇒ 具名PermissionV1.DeniedError(载明 canonical + reason 来源)零 hook 零副作用;ask ⇒ ruleset 末尾追加一条 exact-canonical ask ⇒ 挂起等批准,once/always 即 [REQ-131][CODE] 解析并持久化分层工具策略 #1128 grants,一次调用恰好一问(E3 去重不回潮);allow ⇒ 不加 identity prompt,ability 闸原样。§6 E1–E6 逐行落点
session/tools.tsidentityGate →gateToolExecution(每次调用:重derive subject +resolve()重读 managed+文档)session/llm/request.tsprepare:snapshotCatalogDenied(§6 允许当轮 snapshot;doc-deny 与既有Permission.disabled取并集;host::StructuredOutputsentinel 免疫 exact canonical)tool/code-mode.ts:child catalog 过同一 snapshot 过滤;invokeChildTool顶部同一 gate(deny/ask 早于 hook 早于传输;每子调用重读)session/llm.ts:workflowPreapprovedToolNames第三参docActions(必传,缺席=不预批 fail-closed);snapshot 派生session/prompt.tshandleSubtask:同一 gate(既有 ruleset-disabled 检查保留为双保险)「executor 调用时重读」的变异实测(先 commit 后实验,窗口逐个还原并复核;UTC 时刻)
setRecord收紧、.execute()具名拒绝且真 MCP servertools/call计数不增长;还原(removeRecord)后同一对象恢复、计数 +1git status0 行)三、上一轮「层图加硬依赖 = 23 条全崩」怎么解的
那不是结构障碍,是该节点没进图。
LayerNode.compile走 deps 传递闭包 ⇒ 生产侧只需把AlphaToolPolicy.node加进SessionPrompt.node/LLM.node/ToolRegistry.node的 deps(全在 exclude 文件内);直接调用裸SessionTools.resolve/prepare的测试图必须把节点显式加进自己的LayerNode.group(compile 依赖走Layer.provide,不暴露到成功类型)——harness/闸门/alias-lock 等 5 个图各加一行。R 的传递有两处以句柄切断:prepare走 input 句柄(toolPolicy字段,与其plugin同款),code-mode 走参数句柄(否则 registry materialize 自己的工具 = 类型自环)。23 条探针在补图 + 中性底夹具后断言一字未改全绿。中性底夹具:文档轴接入后 mcp/plugin 类默认 ask(§2 表)。探针矩阵与 execution-gate 量的是 ruleset 轴语义,其中性底加两条 class 层 enabled 记录(走生产
setRecord;用户可达:Settings 两类总开关设启用)。文档轴自己的判据独立成 doc-axis 闸,不与之混。分区隔离:tmpdir instance 的 project.id 跨用例相同 ⇒ 策略文件会跨用例泄漏,4 个写记录的测试文件用生产层的account注入口(#1128 测试口)per-test 隔离——实测泄漏形态是 D3 的 disabled 咬红 D4/D5。四、门(本地实测,全串行;base fail-set 差 = 空)
新增闸门(登记
scripts/gate-files.tsv,assert-gate-files.sh实测 162 文件精确一致):test/tool/alpha-tool-policy-doc-axis-gate.test.ts(7 条 D1–D7):四类默认抵达 executor / 本地类零打扰 / 用户 disabled 双闸具名 / held 对象重读 / binding guard(rebind 回 ask,新旧 server 都零调用)/ quarantine+reset / grant 撬不开 denytest/permission/alpha-tool-inventory.test.ts(5 条 I1–I5)改动的既有判据文件(逐个说明)
packages/ext/src/cloud-websearch-kill.test.ts:两条源码次序锁的锚点从内联.ask(/ctx.ask(换到AlphaToolPolicyGate.gateToolExecution((载体换了,次序不变),并加强:gate 模块内恰有一次input.permission.ask(单一问询点)+ MCP 循环 trigger 与传输之间不许出现 gate 调用。157 条与 base 同数code-mode.test.ts/code-mode-integration.test.ts(上游收编文件):identity ask 的载体从ctx.ask移到 Permission 引擎 ⇒ 3 个探头用例的探针点随之移到 Permission mock(断言的序列/内容不变);harness 补 Permission/policy 层alpha-725-policy-chokepoints.cases.ts:仅 setup 夹具 + E5 调用第三参 + 图加节点,断言零改动,23/23 绿transform.test.ts/prompt.test.ts/alpha-subtask…/alias-lock/tool-identity:补句柄/桩/图;tool-identity 的预批用例按新签名补 docActions 并新增 fail-closed 断言(登记条数 10 不变)主动没做的(与原因)
httpapi/api.ts是上游文件且不在任何收编名单,新增 route 需要一次 ADR 级收编——这超出本票边界(§9.2 边界文件清单),也超出我的授权。已写进设计稿缺口节;[REQ-131][CODE] 设置页新增「工具」节:按来源、服务、单个工具设置停用/询问/允许 #1130 开工前需要一个裁决(收编 api.ts 加 route,或 main 侧直读策略文件 + 另辟 live 枚举通道)。这是本 PR 之外唯一挡在 [REQ-131][CODE] 设置页新增「工具」节:按来源、服务、单个工具设置停用/询问/允许 #1130 面前的缺口ToolBillingFact仅 schema 与 v1/session 类型引用)。inventory 契约携带该字段、恒缺席 ⇒ UI 显示「未知」是真话。补生产方属新能力,不顺手做mcp.bindingFacts做成可选接口方法:上游测试里存量的MCP.Service.of全量桩(north-star 禁改snapshot-tool-race.test.ts,已实测撞门后还原)不必逐个补桩;方法缺席=facts 未知 ⇒ 依赖 digest 的放宽回 ask,只会更严🤖 Generated with Claude Code
https://claude.ai/code/session_01QHDS2BFKuzm9uNH1svU2oj