diff --git a/docs/协作/B03-交付-01.md b/docs/协作/B03-交付-01.md new file mode 100644 index 0000000..6925daf --- /dev/null +++ b/docs/协作/B03-交付-01.md @@ -0,0 +1,100 @@ +# B03 交付 01:完全访问预授权与底部授权替换 + +日期:2026-10-21(Asia/Shanghai)。状态:**已实现;Linux 实际内核/SDK 回环及离线交互验证通过;Windows/客户端重启等剩余项目待验收**,不宣称所有 AC 全量通过。 + +- 需求:[B03-需求](B03-需求.md),YC-007。 +- 开发基线:`0bc9faa1292c4223a61608e72ba3cd13d572252b`。 +- **受测代码 SHA:`adbbb3bd37f6043d10cbaa59d6c28ade6387a7f3`**。 +- B01/B02 及测试清理保持原结论;未启动、修改或中断用户正在运行的会话,未访问原版 WorkBuddy。 + +## 1. 后端实现 + +SDK 实装版本为 `@anthropic-ai/claude-agent-sdk@0.3.304`。采用**SDK default + 宿主显式预授权 gate**,不是把 acceptEdits 误称完全访问,也不启用进程级 bypassPermissions 能力: + +- craft 且用户选择 full-access:PreToolUse 对普通工具预授权 allow;若 SDK 仍转 callback(包括真实 matchedAskRule),callback 同样按有效宿主权限直接 allow,不发人工审批。 +- 默认权限继续使用 SDK 实际判定并进入审批,真实规则匹配仍标记 rule-intercept。 +- plan 使用 SDK plan,ask 使用 default;两者均先经过宿主只读模式边界,full-access 偏好不使其变为 craft。 +- AskUserQuestion 通过 hook ask 保留业务追问回调;ExitPlanMode 保留计划内容展示/拒绝执行分支,不当成普通审批静默放行。 +- 不自动保存全工具 allow 规则,不模拟点击允许,不修改用户全局设置。已有“本次会话始终允许”的 grant 逻辑仍单独存在。 +- 策略切换串行化;切换中阻断执行,过期审批不能应用。SDK 控制失败时关闭不一致进程并锁定失败状态,明确重试 setPolicy 成功后才能恢复/重建。 + +新增白名单脱敏诊断 `[claude-permission]`:宿主权限、agentMode、配置/控制确认的 SDK 模式、分支、匹配 ask-rule 的布尔值、安全分类/未知、原因码是否存在,以及哈希 toolCall 关联。**不保存参数、命令、路径、环境、规则内容或凭据**。SDK mode 字段带来源说明,不是独立 CLI 内部状态探测;原生 EnterPlanMode 自主切换的完整行为未额外验收。 + +SDK `.d.ts` 没有声明的 decisionReasonType/Code 在 `sdk.mjs` 的 wire 转换确有映射;未知/未提供值记录 unknown,不据此反推原始用户七条请求的确切原因。 + +## 2. 前端实现 + +活动工具审批使用 `approvalSlot` 独占底部输入区域,不再挂在完整普通输入框上方。 + +- 普通输入保持挂载以保存草稿/附件/引用/队列,但 hidden、inert、disabled,不能接受焦点、键盘、拖放或发送;普通发送工具栏移除。 +- 业务追问仍是独立的 question 流程,不与工具审批混同。 +- 允许、拒绝、失败/重试、取消及会话切换后恢复输入状态;审批响应和停止操作校验捕获的 session/runId。 +- 取消失败明确展示错误;取消面板按请求标识隔离,旧请求的迟到结果不能污染新审批。 +- 复用现有 Composer/PermissionConfirm 与回归脚本,不另造一套授权业务组件;不恢复已撤回骨架补丁。 + +## 3. 实际内核 + SDK 证据 + +[结果 JSON](evidence/B03-delivery-01/real-kernel-results.json)、[脱敏日志](evidence/B03-delivery-01/real-kernel-loopback.txt)。 + +实际生产 `ClaudeKernel` 打包后仅替换 Electron 的 userData 路径,**SDK query 没有 mock**。真实 Linux CLI 对接固定 SSE 回环模型;临时 HOME/config/userData/workspace,清空环境继承,不使用用户供应商或真实凭据。25 个本地请求、9 个场景全部按预期通过: + +| 场景 | 人工审批 | 实际结果 | +| --- | ---: | --- | +| default craft | 1 | 夹具拒绝 Write,目标未创建 | +| 切为 full craft | 0 | Read/Edit/Write、简单及复合 Bash 成功;文件内容正确;新建后删除的目录/文件不存在,完成标记正确;业务追问 1 次 | +| 切为 plan | 0 | Write 被模式边界拒绝,无目标文件 | +| 切为 ask | 0 | Write 被模式边界拒绝,无目标文件 | +| 返回 default craft | 1 | 再次询问并按夹具拒绝 | +| full craft + 真实 SDK ask:Bash 规则 | 0 | 实际 callback matchedAskRule=true,仍按 full-access 直接执行成功 | +| default + 同一 Bash/规则 | 1 | 真正 rule-approval,夹具拒绝,文件保持不变 | +| 销毁重建并传入 full 偏好 | 0 | Write 与业务追问成功,追问 1 次 | +| full 下不存在目标 Edit、Bash exit 7 | 0 | 2 次真实工具错误,不重新弹权限卡 | + +ask:Bash 仅通过真实 Query 的 session-only `applyFlagSettings` 配置在测试进程中,不写用户设置。真实 SDK/文件检查支持此 gate 选择,而不仅是合成 callback 元数据测试。 + +脚本限制 Linux Bash;Windows/PowerShell 不具备环境时明确阻塞。内部有请求上限、100 秒 abort,执行时另加 120 秒外层截止;结束关闭 query/server 并清理临时目录。没有修改网络或 OS 安全设置;未单独审计 CLI 的所有潜在非模型出站尝试。 + +## 4. 其余回归 + +[离线与构建日志](evidence/B03-delivery-01/verification.txt): + +- `npm test`:退出 0,类型/消息/会话存储/持久化/会话渲染。 +- `test:alignment:dom`(指定现成 jsdom 路径):退出 0,offline 11 套、DOM 7 套;其中 B03 actual-kernel/mock-query policy **276 项**、实际 Composer/PermissionConfirm jsdom **43 项**。 +- `test:reporting`、`test:composer-capabilities`、`test:tool-approvals`:退出 0。 +- `npm run build`:退出 0,含类型检查。 +- `check:tokens`:退出 1,保留相同六项既存失败及计数,没有新增漂移、没有改 baseline。 +- 独立复审重跑 276/43 项,无剩余阻塞性发现;审查发现的取消错误不可见问题已修复。 +- ChatPane 保留基线 CRLF,采用 `git -c core.whitespace=cr-at-eol diff --check` 通过,不为格式统一改写整文件。 + +## 5. AC 状态与未验证项 + +| AC | 本轮证据与剩余范围 | +| --- | --- | +| 7.1 | Linux 原生读写/编辑、新增/删除临时对象、简单/复合 Bash 实际 0 审批;Windows PowerShell、原生独立目录工具及全部后续轮次组合待验 | +| 7.2 | 实际 kernel/SDK default + host gate;真实 ask-rule 下 full 0/default 1;classifier/别名/未知字段由 276 项离线矩阵验证 | +| 7.3 | 实际 default、plan、ask、业务追问和执行错误对照通过;ExitPlanMode 为离线验证,文件系统权限拒绝未实测 | +| 7.4 | 检查实装 SDK 类型与 wire 映射;未知字段策略离线验证,原用户 callback 的具体字段仍无法追溯 | +| 7.5 | 实际同内核切换/返回及销毁重建通过;策略失败闭锁与串行 race 离线通过;客户端重启后持久偏好加载、真实首发 UI 全链仍待 Windows 验收 | +| 7.6 | full 自动执行不写 grants;已有 grant policy/replay 离线通过。真实 SDK session-grant 生命周期尚未完整验证,不把本轮自动预授权测试替代它 | +| 7.7 | 已加入最小脱敏分支记录,真实日志有 matchedAskRule 与宿主决策证据;未知原因码明确 unknown | +| 7.8 | 底部替换由实际组件 DOM/CSS 层叠检查通过;没有取得 Windows 同状态截图或原版像素结果 | +| 7.9 | 43 项覆盖允许/拒绝/失败重试/取消、旧取消迟到、隐藏焦点/发送、真实附件 stage 返回、草稿/引用/队列及请求切换;真实窗口 IME/屏幕阅读器和全应用会话切换仍待验 | + +因此本交付是已实现并取得部分真实 SDK 证据,**不是整个 B03 全量验收通过**。未通过项不得被核心测试或构建绿灯替代。 + +## 6. 复跑与交接 + +按固定代码 SHA 独立安装构建,Windows 应用使用全新 `YCODE_USER_DATA_DIR`,不得操作正在运行的用户会话;dev 启动遵循 Dev 启动 SOP。当前包含 main 代码变更,验收实例应重新启动自己的构建,不复用旧 renderer。 + +```sh +npm ci --legacy-peer-deps +npm test +YCODE_TEST_DOM_MODULE=/absolute/path/to/jsdom npm run test:alignment:dom +npm run build +# 仅 Linux,有真实 SDK CLI 与本地回环权限,执行前阅读脚本: +timeout --signal=TERM --kill-after=5s 120s npm run test:permissions:loopback +``` + +PowerShell 的 DOM 环境变量用 `$env:YCODE_TEST_DOM_MODULE = <路径>`。Windows 验收须另补四类操作/PowerShell、底部授权替换截图、失败恢复及持久偏好重启矩阵。 + +远端推送并核对 SHA 后才算 Git 交接完成。交付后窗口交回验收端,保留旧需求与历史失败记录。 diff --git a/docs/协作/evidence/B03-delivery-01/real-kernel-loopback.txt b/docs/协作/evidence/B03-delivery-01/real-kernel-loopback.txt new file mode 100644 index 0000000..8f4755d --- /dev/null +++ b/docs/协作/evidence/B03-delivery-01/real-kernel-loopback.txt @@ -0,0 +1,24 @@ +[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"43a3b2698eba905e","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"43a3b2698eba905e","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"4ed9abbf3162300a","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"86fd4ab8db7f5f11","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"7e2ee80a5e248272","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"6db1fc2e4c48edb8","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"6e7d36eb4db18cae","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"36814c9006134245","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"business-question"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"36814c9006134245","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"} +[claude-permission] {"permissionMode":"full-access","agentMode":"plan","sdkMode":"plan","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"24d6499c85d11c34","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"} +[claude-permission] {"permissionMode":"full-access","agentMode":"ask","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"410e9145930714a5","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"968c313a624fa4d9","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"968c313a624fa4d9","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"c79ddb7319b70566","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"c79ddb7319b70566","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"37830cdf3606c7c0","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"37830cdf3606c7c0","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"rule-approval"} +[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"9ad2c09ba4cec288","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"8a6a3330fe99a401","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"business-question"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"8a6a3330fe99a401","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"02aeb050b7d4a476","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"} +{"status":"PASS","scope":"Actual ClaudeKernel and SDK; temporary preferences supplied, no Windows/UI coverage","requests":25,"cases":[{"case":"craft-default","approvals":1,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"craft-full","approvals":0,"questions":1,"ruleApprovals":0,"toolErrors":0,"compoundMarker":true,"disposableAbsent":true},{"case":"plan-full","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"ask-full","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"default-return","approvals":1,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"ask-rule-full","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":0},{"case":"ask-rule-default","approvals":1,"questions":0,"ruleApprovals":1,"toolErrors":1},{"case":"rebuilt-full","approvals":0,"questions":1,"ruleApprovals":0,"toolErrors":0},{"case":"full-execution-errors","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":2}]} diff --git a/docs/协作/evidence/B03-delivery-01/real-kernel-results.json b/docs/协作/evidence/B03-delivery-01/real-kernel-results.json new file mode 100644 index 0000000..70ef7e4 --- /dev/null +++ b/docs/协作/evidence/B03-delivery-01/real-kernel-results.json @@ -0,0 +1,77 @@ +{ + "status": "PASS", + "scope": "Actual ClaudeKernel and SDK; temporary preferences supplied, no Windows/UI coverage", + "requests": 25, + "cases": [ + { + "case": "craft-default", + "approvals": 1, + "questions": 0, + "ruleApprovals": 0, + "toolErrors": 1 + }, + { + "case": "craft-full", + "approvals": 0, + "questions": 1, + "ruleApprovals": 0, + "toolErrors": 0, + "compoundMarker": true, + "disposableAbsent": true + }, + { + "case": "plan-full", + "approvals": 0, + "questions": 0, + "ruleApprovals": 0, + "toolErrors": 1 + }, + { + "case": "ask-full", + "approvals": 0, + "questions": 0, + "ruleApprovals": 0, + "toolErrors": 1 + }, + { + "case": "default-return", + "approvals": 1, + "questions": 0, + "ruleApprovals": 0, + "toolErrors": 1 + }, + { + "case": "ask-rule-full", + "approvals": 0, + "questions": 0, + "ruleApprovals": 0, + "toolErrors": 0 + }, + { + "case": "ask-rule-default", + "approvals": 1, + "questions": 0, + "ruleApprovals": 1, + "toolErrors": 1 + }, + { + "case": "rebuilt-full", + "approvals": 0, + "questions": 1, + "ruleApprovals": 0, + "toolErrors": 0 + }, + { + "case": "full-execution-errors", + "approvals": 0, + "questions": 0, + "ruleApprovals": 0, + "toolErrors": 2 + } + ], + "codeSha": "adbbb3bd37f6043d10cbaa59d6c28ade6387a7f3", + "sdkVersion": "0.3.304", + "platform": "linux-x64", + "command": "node scripts/build-full-access-loopback-kernel.mjs && timeout --signal=TERM --kill-after=5s 120s node scripts/test-full-access-loopback.mjs --kernel", + "exitCode": 0 +} diff --git a/docs/协作/evidence/B03-delivery-01/verification.txt b/docs/协作/evidence/B03-delivery-01/verification.txt new file mode 100644 index 0000000..5107a5e --- /dev/null +++ b/docs/协作/evidence/B03-delivery-01/verification.txt @@ -0,0 +1,295 @@ +B03 verification +Code SHA: adbbb3bd37f6043d10cbaa59d6c28ade6387a7f3 +Base: 0bc9faa1292c4223a61608e72ba3cd13d572252b +Linux x64; Node24.19.0; npm11.9.0; SDK0.3.304; jsdom30.1.3 +UI = React/jsdom only; real SDK = isolated actual ClaudeKernel with local deterministic SSE. No user provider/credentials/workspace. +Independent review: 276 offline policy +43 DOM checks; cancellation error visibility fixed before final run. +Diff check uses core.whitespace=cr-at-eol because ChatPane retained original CRLF. + +===== core.txt: exit 0 ===== +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test +> npm run test:core + +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:core +> npm run typecheck && npm run test:chat && npm run test:sessions && npm run test:persistence && npm run test:conversation + +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 typecheck +> tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json + +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:chat +> esbuild scripts/message-order-regression.ts scripts/chat-store-regression.ts scripts/chat-stream-committer-regression.ts --bundle --platform=node --format=esm --out-extension:.js=.mjs --outdir=.tmp/chat-tests --log-level=warning && node .tmp/chat-tests/message-order-regression.mjs && node .tmp/chat-tests/chat-store-regression.mjs && node .tmp/chat-tests/chat-stream-committer-regression.mjs + +message-order-regression: all checks passed +chat-store-regression: all checks passed +chat-stream-committer-regression: all checks passed +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:sessions +> esbuild scripts/session-store-regression.ts --bundle --platform=node --format=esm --external:esbuild --outfile=.tmp/session-store-regression.mjs --log-level=warning && node .tmp/session-store-regression.mjs + +session-store-regression: all checks passed +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:persistence +> esbuild scripts/chat-persistence-regression.ts --bundle --platform=node --format=esm --external:esbuild --outfile=.tmp/chat-persistence-regression.mjs --log-level=warning && node .tmp/chat-persistence-regression.mjs + +chat-persistence-regression: all checks passed +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:conversation +> esbuild scripts/conversation-renderer-regression.tsx scripts/composer-regression.tsx scripts/completed-fold-regression.tsx scripts/streaming-footer-regression.tsx --bundle --platform=node --format=cjs --jsx=automatic --loader:.css=text --out-extension:.js=.cjs --outdir=.tmp/conversation-tests --log-level=error && node .tmp/conversation-tests/conversation-renderer-regression.cjs && node .tmp/conversation-tests/composer-regression.cjs && node .tmp/conversation-tests/streaming-footer-regression.cjs && node .tmp/conversation-tests/completed-fold-regression.cjs + +Conversation specialized renderer SSR regression checks passed +Composer/message action regression cases passed +streaming-footer-regression: persistent stream status, delayed/paused rotation, brand/locale mapping, source CSS, and completed model footer passed +Completed-fold model and SSR regression checks passed +npm notice +npm notice New major version of npm available! 11.9.0 -> 12.2.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0 +npm notice To update run: npm install -g npm@12.2.0 +npm notice +npm notice +npm notice New major version of npm available! 11.9.0 -> 12.2.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0 +npm notice To update run: npm install -g npm@12.2.0 +npm notice +npm notice +npm notice New major version of npm available! 11.9.0 -> 12.2.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0 +npm notice To update run: npm install -g npm@12.2.0 +npm notice + +===== alignment-dom.txt: exit 0 ===== +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:alignment:dom +> node scripts/run-alignment-regression.mjs --require-dom + +PASS model alignment: fresh/legacy migration, new/edit/default/delete/reload, valid selection (offline host fixtures) +PASS model settings: deferred owner switch, rename mapping, addition selection, empty deletion, immutable history +PASS session factory: first-send preference, mode preservation, invalid permission rejection (isolated ports) +{"historyMessages":10000,"bytes":747781,"parseMs":2.9472000000000094,"storeHydrationMs":0.1492190000000022,"note":"Node parsing/store benchmark only, not browser rendering or Windows IPC performance"} +session-composer-alignment: loading/cache/retry/races/model/permissions/modes/SSR passed +alignment-conversation: local groups, original expanded order, question projection and truthful status passed +A01 native MessageBubble identity aliases, immutable inputs and ordinary raw output passed +A01 imported native card, linked dedup and unknown-position compatibility passed +question-answer-shell: structural and recovered CSS contracts passed +question-answer-shell: DOM hierarchy, controls linkage, click, Enter, Space and inert contracts passed +Runtime progress, session-grant scope and approval lifecycle regressions passed +Permission intercept static rendering passed; interactive keyboard/focus remains UI acceptance +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"full-access","agentMode":"ask","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"mode-or-inactive-deny"} +[claude-permission] {"permissionMode":"full-access","agentMode":"plan","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"mode-or-inactive-deny"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"subcommandResults","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"safetyCheck","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":true,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"rule-approval"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"error-deny"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"85aafbf52a5144b5","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"} +[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"85aafbf52a5144b5","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"} +Claude host approval policy unit checks passed (no SDK process/application/matching verification) +[claude-permission] {"permissionMode":"full-access","agentMode":"plan","sdkMode":"plan","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"unknown","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"} +Mock SDK replay lifecycle passed: fail closed, retry, session isolation, independent mode guard +B03 offline host policy: 276 checks passed; no real SDK/CLI/model execution. +task popconfirm DOM regression: 34 checks passed (jsdom, not pixel validation) +question-interaction: 24 DOM behavioral checks passed +question-identity: 30 A01 DOM checks passed (not Electron/pixel/SDK acceptance) +completed-fold-nested: real question/tool/thinking/local-summary remount, event, keyboard and identity contracts passed +completed-fold-native-identity: real reducer done correction, native IDs, insertion/reorder, repeated outer toggles, message isolation and legacy fallback passed +Permission intercept DOM: 43 checks passed (not pixel/SDK verification) +{"checks":37,"passed":true,"scope":"Isolated React DOM and CSS contracts; no native keyboard/layout/pixel acceptance"} +{"result":"PASS","phase":"alignment-offline","suites":11} +{"result":"PASS","phase":"alignment-dom","suites":7} +npm notice +npm notice New major version of npm available! 11.9.0 -> 12.2.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0 +npm notice To update run: npm install -g npm@12.2.0 +npm notice + +===== reporting.txt: exit 0 ===== +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:reporting +> node --test scripts/regression-reporting.test.mjs + +✔ alignment reports absent optional DOM coverage explicitly (2358.188368ms) +✔ alignment requires DOM when requested by flag (68.595048ms) +✔ alignment requires DOM when requested by environment (60.505075ms) +✔ alignment rejects an unloadable configured DOM module instead of skipping (61.004578ms) +✔ backend never reports a skipped real package as PASS (1326.932167ms) +✔ alignment rejects a configured module without a JSDOM export (68.770087ms) +ℹ tests 6 +ℹ suites 0 +ℹ pass 6 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 4030.393006 + +===== composer-capabilities.txt: exit 0 ===== +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:composer-capabilities +> node scripts/run-composer-capabilities-regression.mjs + +prompt-queue-regression: cap, payload, order, isolation, delivery, stop, recovery and unknown checks passed +{ + "result": "PASS", + "checks": [ + { + "name": "parallel same-instance enqueues preserve exactly 19 items", + "pass": true + }, + { + "name": "duplicate take is serialized to one winner", + "pass": true + }, + { + "name": "delivering item is immutable and notify does not duplicate delivery", + "pass": true + }, + { + "name": "clear removes a non-delivering session queue and is idempotent", + "pass": true + }, + { + "name": "first enqueue after an empty queue was paused resumes a new run without unpausing existing work", + "pass": true + }, + { + "name": "incoming payload is validated before host side effects and persistence", + "pass": true + }, + { + "name": "host-rebuilt capability labels are validated before persistence", + "pass": true + }, + { + "name": "two queue instances cannot overwrite one another", + "pass": true + }, + { + "name": "corrupt queue cannot redirect or duplicate item identity", + "pass": true + }, + { + "name": "invalid revision, status and payload permission are rejected", + "pass": true + }, + { + "name": "post-delivery removal failure becomes paused unknown instead of stuck delivering", + "pass": true + }, + { + "name": "stale owner nonce is recovered without trusting a reused PID", + "pass": true + }, + { + "name": "stale and expired lock files are reclaimed", + "pass": true + }, + { + "name": "live foreign lock times out with an explicit error", + "pass": true + }, + { + "name": "blocked notify does not create a state revision", + "pass": true + }, + { + "name": "host resolver applies dispatch-time permission downgrade without mutating stored payload", + "pass": true + } + ] +} +input-composition-regression: precedence, takeover, queue preservation, task placement, toolbar and escape rules passed +{"result":"PASS","checks":30} +{ + "result": "PASS", + "tests": [ + "serial model writes + frozen active turn", + "send failure retry", + "late result/event session isolation", + "draft settings during first session creation", + "nextRequestSettings whitelist" + ] +} +context-usage-regression: latest, previous, active-run, summary identity and failure cases passed +{"result":"PASS","checks":36,"directory":"/workspace/scratch/0aaa9774aecc/single-package-staging/ycode/.tmp/claude-capabilities-i8WXcM"} +npm notice +npm notice New major version of npm available! 11.9.0 -> 12.2.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0 +npm notice To update run: npm install -g npm@12.2.0 +npm notice + +===== tool-approvals.txt: exit 0 ===== +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 test:tool-approvals +> esbuild scripts/tool-approval-regression.tsx --bundle --platform=node --format=cjs --jsx=automatic --loader:.css=text --outfile=.tmp/tool-approval-regression.cjs --log-level=error && node .tmp/tool-approval-regression.cjs + +Tool approval helper and inline source markup regression checks passed. + +===== build.txt: exit 0 ===== +Successful full build including typecheck; tail follows: +out/renderer/assets/cytoscape.esm-bVGYt-iW.js 869.69 kB +out/renderer/assets/ArtifactPierreDiff-D5xhRc5y.js 1,119.58 kB +out/renderer/assets/chunk-FOHPRMQF-BCllzKJD.js 1,154.18 kB +out/renderer/assets/index-dE2T-qjC.js 3,765.40 kB +out/renderer/assets/editor.api2-dPwET-7w-BYIQ9bT3.js 4,889.23 kB + +✓ built in 1.86s +npm notice +npm notice New major version of npm available! 11.9.0 -> 12.2.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v12.2.0 +npm notice To update run: npm install -g npm@12.2.0 +npm notice +===== tokens.txt: exit 1 ===== +npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. + +> ycode@0.0.7 check:tokens +> node scripts/check-design-tokens.mjs + +设计 token 漂移检查(静态) + 扫描:src/renderer/src 共 367 个文件(用时 46 ms) + baseline:scripts/design-token-baseline.json(334 个文件) + 门禁分类:adapter 8 | core 6 | local 279(合计 293 个文件) + 合计:裸 hex=611 裸 px=2680 !important=6 --wb-* 定义=525 var(--yc-*) 使用=1651 var(--wb-*) 使用=1209 + 非门禁分类:vendor 2 | recovered 22 | source 47 | tokenSource 3(合计 74 个文件,仅记录不阻塞) + 合计:裸 hex=10642 裸 px=13642 !important=920 --wb-* 定义=17966 var(--yc-*) 使用=77 var(--wb-*) 使用=19638 + 非门禁相对 baseline:文件 +0;裸 hex +78 裸 px +64 !important +0 --wb-* 定义 +0 var(--yc-*) 使用 +22 var(--wb-*) 使用 -120 + +结果:失败,共 6 项: + [新增门禁文件] src/renderer/src/capabilities/recommended-flow.css(local):裸 px=21 + [新增门禁文件] src/renderer/src/capabilities/skill-detail-shell.css(local):裸 px=21 + [回归] src/renderer/src/capabilities/skills-host.css(local):裸 px 25 → 45(+20) + [新增门禁文件] src/renderer/src/workbuddy/composer/capability-picker.css(local):裸 hex=26,裸 px=48 + [回归] src/renderer/src/workbuddy/composer/composer.css(local):裸 hex 23 → 38(+15);裸 px 83 → 139(+56) + [新增门禁文件] src/renderer/src/workbuddy/composer/prompt-queue.css(local):裸 hex=8,裸 px=35 + +提示:确认变更符合预期后运行 `node scripts/check-design-tokens.mjs --update-baseline` 刷新 baseline; + 否则请改用 --yc-* token、复用现有值,或去掉重复的 --wb-* 定义。 +提示(不失败,仅记录):3 个门禁文件 token 使用数上升: + src/renderer/src/capabilities/skills-host.css(local):var(--wb-*) 使用 12 → 19(+7) + src/renderer/src/workbuddy/composer/composer.css(local):var(--yc-*) 使用 35 → 48(+13);var(--wb-*) 使用 0 → 1(+1) + src/renderer/src/workbuddy/conversation/conversation.css(local):var(--yc-*) 使用 0 → 4(+4) +提示(不失败):baseline 中 8 个文件已不存在:src/renderer/src/components/ReportedRunUsage.tsx;src/renderer/src/workbuddy/subagents/SourceMemberIcon.tsx;src/renderer/src/workbuddy/subagents/SubagentCollaboration.tsx;src/renderer/src/workbuddy/subagents/SubagentDetailPanel.tsx;src/renderer/src/workbuddy/subagents/adapters.css;src/renderer/src/workbuddy/subagents/member-view.ts;src/renderer/src/workbuddy/subagents/source.css;src/renderer/src/workbuddy/subagents/theme.css +提示:新增门禁文件 36 个且无受控计数(允许):src/renderer/src/capabilities/CapabilityMaintenance.tsx(local);src/renderer/src/capabilities/RecommendedSkills.tsx(local);src/renderer/src/capabilities/SkillAvatar.tsx(local);src/renderer/src/capabilities/SkillDetailShell.tsx(local);src/renderer/src/capabilities/SkillModalPortal.tsx(local);src/renderer/src/capabilities/skill-modal-focus.ts(local);src/renderer/src/components/SessionLoading.tsx(local);src/renderer/src/components/TaskPopconfirm.tsx(local);src/renderer/src/components/session-loading.css(local);src/renderer/src/components/task-popconfirm.css(local);src/renderer/src/components/updates/UpdateSidebarCard.tsx(local);src/renderer/src/components/updates/update-ui-model.ts(local);src/renderer/src/components/updates/update-ui-store.ts(local);src/renderer/src/components/updates/updates-ui.css(local);src/renderer/src/ui/Button.tsx(local);src/renderer/src/ui/IconButton.tsx(local);src/renderer/src/ui/Input.tsx(local);src/renderer/src/ui/Popover.tsx(local);src/renderer/src/ui/Select.tsx(local);src/renderer/src/ui/Switch.tsx(local);…(还有 16 项,详见 --json)